kdb_plus_fixed/api/mod.rs
1//! This `api` module provides API mirroring the C API of q/kdb+. The expected usage is to build a shared library for q/kdb+ in Rust.
2//!
3//! In order to avoid writing too large `unsafe` block leading to poor optimization, most of native C API functions were provided
4//! with a wrapper funtion with a bit of ergonomic safety and with intuitive implementation as a trait method. The only exceptions
5//! are:
6//! - `knk`
7//! - `k`
8//! These functions are using elipsis (`...`) as its argument and cannot be provided with a stable distribution. When you need to use
9//! either of them you can find them under `native` namespace together with the other naked C API functions.
10//!
11//! *Notes:*
12//!
13//! - This library is for kdb+ version >= 3.0.
14//! - Meangless C macros are excluded but accessors of an underlying array like `kC`, `kJ`, `kK` etc. are provided in Rust way.
15//!
16//! ## Examples
17//!
18//! In order to encourage to use Rust style API, examples of the C API style is not provided here (you can see them in [README of the repository](https://github.com/diamondrod/kdbplus)).
19//! The examples below are written without `unsafe` code. You can see how comfortably breathing are the wrapped functions in the code.
20//!
21//! ```no_run
22//! #[macro_use]
23//! extern crate kdbplus;
24//! use kdbplus::api::*;
25//! use kdbplus::qtype;
26//!
27//! #[no_mangle]
28//! pub extern "C" fn create_symbol_list2(_: K) -> K{
29//! let mut list=new_list(qtype::SYMBOL_LIST, 0);
30//! list.push_symbol("Abraham").unwrap();
31//! list.push_symbol("Isaac").unwrap();
32//! list.push_symbol("Jacob").unwrap();
33//! list.push_symbol_n("Josephine", 6).unwrap();
34//! list
35//! }
36//!
37//! #[no_mangle]
38//! fn no_panick(func: K, args: K) -> K{
39//! let result=error_to_string(apply(func, args));
40//! if let Ok(error) = result.get_error_string(){
41//! println!("FYI: {}", error);
42//! // Decrement reference count of the error object which is no longer used.
43//! decrement_reference_count(result);
44//! KNULL
45//! }
46//! else{
47//! println!("success!");
48//! result
49//! }
50//! }
51//!
52//! #[no_mangle]
53//! pub extern "C" fn create_table2(_: K) -> K{
54//! // Build keys
55//! let keys=new_list(qtype::SYMBOL_LIST, 2);
56//! let keys_slice=keys.as_mut_slice::<S>();
57//! keys_slice[0]=enumerate(str_to_S!("time"));
58//! keys_slice[1]=enumerate_n(str_to_S!("temperature_and_humidity"), 11);
59//!
60//! // Build values
61//! let values=new_list(qtype::COMPOUND_LIST, 2);
62//! let time=new_list(qtype::TIMESTAMP_LIST, 3);
63//! // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
64//! time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
65//! let temperature=new_list(qtype::FLOAT_LIST, 3);
66//! temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
67//! values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
68//!
69//! flip(new_dictionary(keys, values))
70//! }
71//! ```
72//!
73//! And q code is here:
74//!
75//! ```q
76//! q)summon:`libapi_examples 2: (`create_symbol_list2; 1)
77//! q)summon[]
78//! `Abraham`Isaac`Jacob`Joseph
79//! q)chill: `libapi_examples 2: (`no_panick; 2);
80//! q)chill[$; ("J"; "42")]
81//! success!
82//! 42
83//! q)chill[+; (1; `a)]
84//! FYI: type
85//! q)climate_change: libc_api_examples 2: (`create_table2; 1);
86//! q)climate_change[]
87//! time temperature
88//! -----------------------------------------
89//! 2003.10.10D02:24:19.167018272 22.1
90//! 2006.05.24D06:16:49.419710368 24.7
91//! 2008.08.12D23:12:24.018691392 30.5
92//! ```
93
94//++++++++++++++++++++++++++++++++++++++++++++++++++//
95// >> Settings
96//++++++++++++++++++++++++++++++++++++++++++++++++++//
97
98#![allow(non_upper_case_globals)]
99#![allow(non_camel_case_types)]
100#![allow(non_snake_case)]
101#![allow(clippy::not_unsafe_ptr_arg_deref)]
102#![allow(clippy::wrong_self_convention)]
103#![allow(clippy::len_without_is_empty)]
104
105//++++++++++++++++++++++++++++++++++++++++++++++++++//
106// >> Load Libraries
107//++++++++++++++++++++++++++++++++++++++++++++++++++//
108
109use super::qtype;
110use std::convert::TryInto;
111use std::ffi::CStr;
112use std::os::raw::{
113 c_char, c_double, c_float, c_int, c_longlong, c_schar, c_short, c_uchar, c_void,
114};
115use std::str;
116pub mod native;
117
118//++++++++++++++++++++++++++++++++++++++++++++++++++//
119// >> Global Variables
120//++++++++++++++++++++++++++++++++++++++++++++++++++//
121
122/// `K` nullptr. This value can be used as void value of a function which is called directly by q process
123/// and returns `K`. This null pointer is interpreted as a general null value (`::`) whose type is `101h`.
124/// # Example
125/// ```
126/// use kdbplus::api::*;
127///
128/// #[no_mangle]
129/// pub extern "C" fn vanity(_: K) -> K{
130/// println!("Initialized something, probably it is your mindset.");
131/// KNULL
132/// }
133/// ```
134/// # Warning
135/// This value must NOT be used as a returned value for functions called by another function
136/// because [`error_to_string`](fn.error_to_string.html) misunderstands the value as an error.
137/// For detail, see its warning section.
138pub const KNULL: K = 0 as K;
139
140//++++++++++++++++++++++++++++++++++++++++++++++++++//
141// >> Macros
142//++++++++++++++++++++++++++++++++++++++++++++++++++//
143
144//%% Utility %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
145
146/// Convert `&str` to `S` (null-terminated character array).
147/// # Example
148/// ```no_run
149/// #[macro_use]
150/// use kdbplus::api::*;
151///
152/// #[no_mangle]
153/// pub extern "C" fn pingpong(_: K) -> K{
154/// unsafe{native::k(0, str_to_S!("ping"), new_int(77), KNULL)}
155/// }
156/// ```
157/// ```q
158/// q)ping:{[int] `$string[int], "_pong!!"}
159/// q)pingpong: `libapi_examples 2: (`pingpong; 1);
160/// q)pingpong[]
161/// `77_pong!!
162/// ```
163/// # Note
164/// This macro cannot be created as a function due to freeing resource of Rust (not sure).
165#[macro_export]
166macro_rules! str_to_S {
167 ($string: expr) => {
168 [$string.as_bytes(), &[b'\0']].concat().as_mut_ptr() as S
169 };
170}
171
172//++++++++++++++++++++++++++++++++++++++++++++++++++//
173// >> Structs
174//++++++++++++++++++++++++++++++++++++++++++++++++++//
175
176//%% Alias %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
177
178/// `char*` in C. Also used to access symbol of q.
179pub type S = *mut c_char;
180/// `const char*` in C.
181pub type const_S = *const c_char;
182/// `char` in C. Also used to access char of q.
183pub type C = c_char;
184/// `unsigned char` in C. Also used to access byte of q.
185pub type G = c_uchar;
186/// `i16` in C. Also used to access short of q.
187pub type H = c_short;
188/// `i32` in C. Also used to access int and compatible types (month, date, minute, second and time) of q.
189pub type I = c_int;
190/// `i64` in C. Also used to access long and compatible types (timestamp and timespan) of q.
191pub type J = c_longlong;
192/// `f32` in C. Also used to access real of q.
193pub type E = c_float;
194/// `f64` in C. Also used to access float and datetime of q.
195pub type F = c_double;
196/// `void` in C.
197pub type V = c_void;
198
199//%% U %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
200
201/// Struct representing 16-bytes GUID.
202#[derive(Clone, Copy, Debug)]
203#[repr(C)]
204pub struct U {
205 pub guid: [G; 16],
206}
207
208//%% K %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
209
210/// Underlying list value of q object.
211/// # Note
212/// Usually this struct does not need to be accessed this struct directly unless user wants to
213/// access via a raw pointer for non-trivial stuff.
214#[derive(Clone, Copy, Debug)]
215#[repr(C)]
216pub struct k0_list {
217 /// Length of the list.
218 pub n: J,
219 /// Pointer referring to the head of the list. This pointer will be interpreted
220 /// as various types when accessing `K` object to edit the list with
221 /// [`as_mut_slice`](trait.KUtility.html#tymethod.as_mut_slice).
222 pub G0: [G; 1],
223}
224
225/// Underlying atom value of q object.
226/// # Note
227/// Usually this struct does not need to be accessed directly unless user wants to
228/// access via a raw pointer for non-trivial stuff.
229#[derive(Clone, Copy)]
230#[repr(C)]
231pub union k0_inner {
232 /// Byte type holder.
233 pub byte: G,
234 /// Short type holder.
235 pub short: H,
236 /// Int type holder.
237 pub int: I,
238 /// Long type older.
239 pub long: J,
240 /// Real type holder.
241 pub real: E,
242 /// Float type holder.
243 pub float: F,
244 /// Symbol type holder.
245 pub symbol: S,
246 /// Table type holder.
247 pub table: *mut k0,
248 /// List type holder.
249 pub list: k0_list,
250}
251
252/// Underlying struct of `K` object.
253#[repr(C)]
254#[derive(Clone, Copy)]
255pub struct k0 {
256 /// For internal usage.
257 m: c_schar,
258 /// For internal usage.
259 a: c_schar,
260 /// Type indicator.
261 pub qtype: c_schar,
262 /// Attribute of list.
263 pub attribute: C,
264 /// Reference count of the object.
265 pub refcount: I,
266 /// Underlying value.
267 pub value: k0_inner,
268}
269
270/// Struct representing q object.
271pub type K = *mut k0;
272
273//++++++++++++++++++++++++++++++++++++++++++++++++++//
274// >> Structs
275//++++++++++++++++++++++++++++++++++++++++++++++++++//
276
277//%% KUtility %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
278
279/// Trait which defines utility methods to manipulate q object.
280pub trait KUtility {
281 /// Derefer `K` as a mutable slice of the specified type. The supported types are:
282 /// - `G`: Equivalent to C API macro `kG`.
283 /// - `H`: Equivalent to C API macro `kH`.
284 /// - `I`: Equivalent to C API macro `kI`.
285 /// - `J`: Equivalent to C API macro `kJ`.
286 /// - `E`: Equivalent to C API macro `kE`.
287 /// - `F`: Equivalent to C API macro `kF`.
288 /// - `C`: Equivalent to C API macro `kC`.
289 /// - `S`: Equivalent to C API macro `kS`.
290 /// - `K`: Equivalent to C API macro `kK`.
291 /// # Example
292 /// ```
293 /// use kdbplus::api::*;
294 ///
295 /// #[no_mangle]
296 /// pub extern "C" fn modify_long_list_a_bit(long_list: K) -> K{
297 /// if long_list.len() >= 2{
298 /// // Derefer as a mutable i64 slice.
299 /// long_list.as_mut_slice::<J>()[1]=30000_i64;
300 /// // Increment the counter to reuse on q side.
301 /// increment_reference_count(long_list)
302 /// }
303 /// else{
304 /// new_error("this list is not long enough. how ironic...\0")
305 /// }
306 /// }
307 /// ```
308 /// ```q
309 /// q)ironic: `libapi_examples 2: (`modify_long_list_a_bit; 1);
310 /// q)list:1 2 3;
311 /// q)ironic list
312 /// 1 30000 3
313 /// q)ironic enlist 1
314 /// ```
315 /// # Note
316 /// Intuitively the parameter should be `&mut self` but it restricts a manipulating
317 /// `K` objects in the form of slice simultaneously. As copying a pointer is not
318 /// an expensive operation, using `self` should be fine.
319 fn as_mut_slice<'a, T>(self) -> &'a mut [T];
320
321 /// Get an underlying q byte.
322 /// # Example
323 /// ```no_run
324 /// use kdbplus::api::*;
325 ///
326 /// #[no_mangle]
327 /// pub extern "C" fn print_bool(atom: K) -> K{
328 /// match atom.get_bool(){
329 /// Ok(boolean) => {
330 /// println!("bool: {}", boolean);
331 /// KNULL
332 /// },
333 /// Err(error) => new_error(error)
334 /// }
335 /// }
336 /// ```
337 /// ```q
338 /// q)print_boole: `libapi_examples 2: (`print_bool; 1);
339 /// q)print_bool[1b]
340 /// bool: true
341 /// ```
342 fn get_bool(&self) -> Result<bool, &'static str>;
343
344 /// Get an underlying q byte.
345 /// # Example
346 /// ```no_run
347 /// use kdbplus::api::*;
348 ///
349 /// #[no_mangle]
350 /// pub extern "C" fn print_guid(atom: K) -> K{
351 /// match atom.get_guid(){
352 /// Ok(guid) => {
353 /// let strguid=guid.iter().map(|b| format!("{:02x}", b)).collect::<String>();
354 /// println!("GUID: {}-{}-{}-{}-{}", &strguid[0..4], &strguid[4..6], &strguid[6..8], &strguid[8..10], &strguid[10..16]);
355 /// KNULL
356 /// },
357 /// Err(error) => new_error(error)
358 /// }
359 /// }
360 /// ```
361 /// ```q
362 /// q)print_guid: `libapi_examples 2: (`print_guid; 1);
363 /// q)guid: first 1?0Ng;
364 /// q)print_guid[guid]
365 /// GUID: 8c6b-8b-64-68-156084
366 /// ```
367 fn get_guid(&self) -> Result<[u8; 16], &'static str>;
368
369 /// Get an underlying q byte.
370 /// # Example
371 /// ```no_run
372 /// use kdbplus::api::*;
373 ///
374 /// #[no_mangle]
375 /// pub extern "C" fn print_byte(atom: K) -> K{
376 /// match atom.get_byte(){
377 /// Ok(byte) => {
378 /// println!("byte: {:#4x}", byte);
379 /// KNULL
380 /// },
381 /// Err(error) => new_error(error)
382 /// }
383 /// }
384 /// ```
385 /// ```q
386 /// q)print_byte: `libapi_examples 2: (`print_byte; 1);
387 /// q)print_byte[0xc4]
388 /// byte: 0xc4
389 /// ```
390 fn get_byte(&self) -> Result<u8, &'static str>;
391
392 /// Get an underlying q short.
393 /// # Example
394 /// ```no_run
395 /// use kdbplus::api::*;
396 ///
397 /// #[no_mangle]
398 /// pub extern "C" fn print_short(atom: K) -> K{
399 /// match atom.get_short(){
400 /// Ok(short) => {
401 /// println!("short: {}", short);
402 /// KNULL
403 /// },
404 /// Err(error) => new_error(error)
405 /// }
406 /// }
407 /// ```
408 /// ```q
409 /// q)print_short: `libapi_examples 2: (`print_short; 1);
410 /// q)print_short[10h]
411 /// short: 10
412 /// ```
413 fn get_short(&self) -> Result<i16, &'static str>;
414
415 /// Get an underlying q int.
416 /// # Example
417 /// ```no_run
418 /// use kdbplus::api::*;
419 ///
420 /// #[no_mangle]
421 /// pub extern "C" fn print_int(atom: K) -> K{
422 /// match atom.get_int(){
423 /// Ok(int) => {
424 /// println!("int: {}", int);
425 /// KNULL
426 /// },
427 /// Err(error) => new_error(error)
428 /// }
429 /// }
430 /// ```
431 /// ```q
432 /// q)print_int: `libapi_examples 2: (`print_int; 1);
433 /// q)print_int[03:57:20]
434 /// int: 14240
435 /// ```
436 fn get_int(&self) -> Result<i32, &'static str>;
437
438 /// Get an underlying q long.
439 /// # Example
440 /// ```no_run
441 /// use kdbplus::api::*;
442 ///
443 /// #[no_mangle]
444 /// pub extern "C" fn print_long(atom: K) -> K{
445 /// match atom.get_long(){
446 /// Ok(long) => {
447 /// println!("long: {}", long);
448 /// KNULL
449 /// },
450 /// Err(error) => new_error(error)
451 /// }
452 /// }
453 /// ```
454 /// ```q
455 /// q)print_long: `libapi_examples 2: (`print_long; 1);
456 /// q)print_long[2000.01.01D12:00:00.123456789]
457 /// long: 43200123456789
458 /// ```
459 fn get_long(&self) -> Result<i64, &'static str>;
460
461 /// Get an underlying q real.
462 /// # Example
463 /// ```no_run
464 /// use kdbplus::api::*;
465 ///
466 /// #[no_mangle]
467 /// pub extern "C" fn print_real(atom: K) -> K{
468 /// match atom.get_real(){
469 /// Ok(real) => {
470 /// println!("real: {}", real);
471 /// KNULL
472 /// },
473 /// Err(error) => new_error(error)
474 /// }
475 /// }
476 /// ```
477 /// ```q
478 /// q)print_real: `libapi_examples 2: (`print_real; 1);
479 /// q)print_real[193810.32e]
480 /// real: 193810.31
481 /// ```
482 fn get_real(&self) -> Result<f32, &'static str>;
483
484 /// Get an underlying q float.
485 /// # Example
486 /// ```no_run
487 /// use kdbplus::api::*;
488 ///
489 /// #[no_mangle]
490 /// pub extern "C" fn print_float(atom: K) -> K{
491 /// match atom.get_float(){
492 /// Ok(float) => {
493 /// println!("float: {:.8}", float);
494 /// KNULL
495 /// },
496 /// Err(error) => new_error(error)
497 /// }
498 /// }
499 /// ```
500 /// ```q
501 /// q)print_float: `libapi_examples 2: (`print_float; 1);
502 /// q)print_float[2002.01.12T10:03:45.332]
503 /// float: 742.41927468
504 /// ```
505 fn get_float(&self) -> Result<f64, &'static str>;
506
507 /// Get an underlying q char.
508 /// # Example
509 /// ```no_run
510 /// use kdbplus::api::*;
511 ///
512 /// #[no_mangle]
513 /// pub extern "C" fn print_char(atom: K) -> K{
514 /// match atom.get_char(){
515 /// Ok(character) => {
516 /// println!("char: \"{}\"", character);
517 /// KNULL
518 /// },
519 /// Err(error) => new_error(error)
520 /// }
521 /// }
522 /// ```
523 /// ```q
524 /// q)print_char: `libapi_examples 2: (`print_char; 1);
525 /// q)print_char["k"]
526 /// char: "k"
527 /// ```
528 fn get_char(&self) -> Result<char, &'static str>;
529
530 /// Get an underlying q symbol.
531 /// # Example
532 /// ```no_run
533 /// use kdbplus::api::*;
534 ///
535 /// #[no_mangle]
536 /// pub extern "C" fn print_symbol2(atom: K) -> K{
537 /// match atom.get_symbol(){
538 /// Ok(symbol) => {
539 /// println!("symbol: `{}", symbol);
540 /// KNULL
541 /// },
542 /// Err(error) => new_error(error)
543 /// }
544 /// }
545 /// ```
546 /// ```q
547 /// q)print_symbol2: `libapi_examples 2: (`print_symbol2; 1);
548 /// q)print_symbol2[`locust]
549 /// symbol: `locust
550 /// ```
551 fn get_symbol(&self) -> Result<&str, &'static str>;
552
553 /// Get an underlying q string as `&str`.
554 /// # Example
555 /// ```no_run
556 /// use kdbplus::api::*;
557 ///
558 /// #[no_mangle]
559 /// pub extern "C" fn print_string(string: K) -> K{
560 /// match string.get_str(){
561 /// Ok(string_) => {
562 /// println!("string: \"{}\"", string_);
563 /// KNULL
564 /// },
565 /// Err(error) => new_error(error)
566 /// }
567 /// }
568 /// ```
569 /// ```q
570 /// q)print_string: `libapi_examples 2: (`print_string; 1);
571 /// q)print_string["gnat"]
572 /// string: "gnat"
573 /// ```
574 fn get_str(&self) -> Result<&str, &'static str>;
575
576 /// Get an underlying q string as `String`.
577 /// # Example
578 /// ```no_run
579 /// use kdbplus::api::*;
580 ///
581 /// #[no_mangle]
582 /// pub extern "C" fn print_string2(string: K) -> K{
583 /// match string.get_string(){
584 /// Ok(string_) => {
585 /// println!("string: \"{}\"", string_);
586 /// KNULL
587 /// },
588 /// Err(error) => new_error(error)
589 /// }
590 /// }
591 /// ```
592 /// ```q
593 /// q)print_string: `libapi_examples 2: (`print_string; 1);
594 /// q)print_string["grasshopper"]
595 /// string: "grasshopper"
596 /// ```
597 fn get_string(&self) -> Result<String, &'static str>;
598
599 /// Get a flipped underlying q table as `K` (dictionary).
600 /// # Example
601 /// ```no_run
602 /// use kdbplus::api::*;
603 ///
604 /// #[no_mangle]
605 /// pub extern "C" fn hidden_key(table: K) -> K{
606 /// match table.get_dictionary(){
607 /// Ok(dictionary) => dictionary.as_mut_slice::<K>()[0].q_ipc_encode(3).unwrap(),
608 /// Err(error) => new_error(error)
609 /// }
610 /// }
611 /// ```
612 /// ```q
613 /// q)perceive_the_man: `libapi_examples 2: (`hidden_key; 1);
614 /// q)perceive_the_man ([] t: `timestamp$.z.p+1e9*til 9; chr:"ljppkgfgs"; is: 7 8 12 14 21 316 400 1000 6000i)
615 /// 0x01000000170000000b0003000000740063687200697300
616 /// ```
617 /// # Note
618 /// This method is provided because the ony way to examine the value of table type is to access the underlying dictionary (flipped table).
619 /// Also when some serialization is necessary for a table, you can reuse a serializer for a dictionary if it is already provided. Actually
620 /// when q serialize a table object with `-8!` (q function) or `b9` (C code), it just serializes the underlying dictionary with an additional
621 /// marker indicating a table type.
622 fn get_dictionary(&self) -> Result<K, &'static str>;
623
624 /// Get an underlying error symbol as `&str`. This function avoids false positive of processing `KNULL` as an error.
625 /// # Example
626 /// See the example of [`error_to_string`](fn.error_to_string.html).
627 fn get_error_string(&self) -> Result<&str, &'static str>;
628
629 /// Get a table row of the given index. For enumerated column, a names of a target `sym` list
630 /// to which symbol values are cast must be passed. In the example below, it is assumed that
631 /// there is a single enum column in a table and the column values are cast to a symbol list whose name is `sym`.
632 /// ```no_run
633 /// use kdbplus::api::*;
634 /// use kdbplus::qtype;
635 ///
636 /// #[no_mangle]
637 /// pub extern "C" fn print_row(object: K, index: K) -> K{
638 /// match object.get_type(){
639 /// qtype::TABLE => {
640 /// match object.get_row(index.get_long().unwrap() as usize, &["sym"]){
641 /// Ok(row) => {
642 /// let null = unsafe{k(0, str_to_S!("{-1 \"row: \", .Q.s1 x}"), row, KNULL)};
643 /// decrement_reference_count(null);
644 /// KNULL
645 /// }
646 /// Err(error) => new_error(error)
647 /// }
648 /// },
649 /// _ => new_error("not a table\0")
650 /// }
651 /// }
652 /// ```
653 /// ```q
654 /// q)row: `libapi_examples 2: (`print_row; 2)
655 /// q)table: ([] time: asc `timestamp$.z.p + 3?1000000000; sym: -3?`Green`Yellow`Red; go: "oxx"; miscellaneous: ("cow"; `lion; "eagle"))
656 /// q)row[table;2]
657 /// row: `time`sym`go`miscellaneous!(2022.01.30D07:55:48.404520689;`Yellow;"x";"eagle")
658 /// q)row[table;1]
659 /// row: `time`sym`go`miscellaneous!(2022.01.30D07:55:47.987133353;`Green;"x";`lion)
660 /// ```
661 fn get_row(&self, index: usize, enum_sources: &[&str]) -> Result<K, &'static str>;
662
663 /// Get an attribute of a q object.
664 /// # Example
665 /// ```no_run
666 /// use kdbplus::api::*;
667 /// use kdbplus::qattribute;
668 ///
669 /// #[no_mangle]
670 /// pub extern "C" fn murmur(list: K) -> K{
671 /// match list.get_attribute(){
672 /// qattribute::SORTED => {
673 /// new_string("Clean")
674 /// },
675 /// qattribute::UNIQUE => {
676 /// new_symbol("Alone")
677 /// },
678 /// _ => KNULL
679 /// }
680 /// }
681 /// ```
682 fn get_attribute(&self) -> C;
683
684 /// Get a reference count of a q object.
685 fn get_refcount(&self) -> I;
686
687 /// Append a q list object to a q list.
688 /// Returns a pointer to the (potentially reallocated) `K` object.
689 /// ```no_run
690 /// use kdbplus::api::*;
691 ///
692 /// #[no_mangle]
693 /// pub extern "C" fn concat_list2(mut list1: K, list2: K) -> K{
694 /// if let Err(err) = list1.append(increment_reference_count(list2)){
695 /// new_error(err)
696 /// }
697 /// else{
698 /// increment_reference_count(list1)
699 /// }
700 /// }
701 /// ```
702 /// ```q
703 /// q)plunder: `libapi_examples 2: (`concat_list2; 2);
704 /// q)plunder[(::; `metals; `fire); ("clay"; 316)]
705 /// ::
706 /// `metals
707 /// `fire
708 /// "clay"
709 /// 316
710 /// q)plunder[1 2 3; 4 5]
711 /// 1 2 3 4 5
712 /// q)plunder[`a`b`c; `d`e]
713 /// `a`b`c`d`e
714 /// ```
715 /// # Note
716 /// While native function [`jv`](native/fn.jv.html) does not consume the appended list,
717 /// this function does for intuitiveness. To append externally provided list (i.e., passed
718 /// from q process), apply [`increment_reference_count`](fn.increment_reference_count.html)
719 /// before appending the list.
720 fn append(&mut self, list: K) -> Result<K, &'static str>;
721
722 /// Add a q object to a q compound list while the appended one is consumed.
723 /// Returns a pointer to the (potentially reallocated) `K` object.
724 /// # Example
725 /// ```no_run
726 /// use kdbplus::api::*;
727 /// use kdbplus::qtype;
728 ///
729 /// #[no_mangle]
730 /// pub extern "C" fn create_compound_list(int: K) -> K{
731 /// let mut list=new_list(qtype::COMPOUND_LIST, 0);
732 /// for i in 0..5{
733 /// list.push(new_long(i)).unwrap();
734 /// }
735 /// list.push(increment_reference_count(int)).unwrap();
736 /// list
737 /// }
738 /// ```
739 /// ```q
740 /// q)nums: `libapi_examples 2: (`create_compound_list2; 1);
741 /// q)nums[5i]
742 /// 0
743 /// 1
744 /// 2
745 /// 3
746 /// 4
747 /// 5i
748 /// ```
749 /// # Note
750 /// In this example we did not allocate an array as `new_list(qtype::COMPOUND_LIST, 0)` to use `push`.
751 /// As `new_list` initializes the internal list size `n` with its argument, preallocating memory with `new_list` and
752 /// then using `push` will crash. If you want to allocate a memory in advance, you can substitute a value
753 /// after converting the q list object into a slice with [`as_mut_slice`](rait.KUtility.html#tymethod.as_mut_slice).
754 fn push(&mut self, atom: K) -> Result<K, &'static str>;
755
756 /// Add a raw value to a q simple list and returns a pointer to the (potentially reallocated) `K` object.
757 /// # Example
758 /// ```no_run
759 /// use kdbplus::api::*;
760 /// use kdbplus::qtype;
761 ///
762 /// #[no_mangle]
763 /// pub extern "C" fn create_simple_list2(_: K) -> K{
764 /// let mut list=new_list(qtype::DATE_LIST, 0);
765 /// for i in 0..5{
766 /// list.push_raw(i).unwrap();
767 /// }
768 /// list
769 /// }
770 /// ```
771 /// ```q
772 /// q)simple_is_the_best: `lic_api_example 2: (`create_simple_list2; 1);
773 /// q)simple_is_the_best[]
774 /// 2000.01.01 2000.01.02 2000.01.03 2000.01.04 2000.01.05
775 /// ```
776 /// # Note
777 /// - Concrete type of `T` is not checked. Its type must be either of `I`, `J`, `E` and `F` and it must be compatible
778 /// with the list type. For example, timestamp list requires `J` type atom.
779 /// - For symbol list, use [`push_symbol`](#fn.push_symbol) or [`push_symbol_n`](#fn.push_symbol_n).
780 fn push_raw<T>(&mut self, atom: T) -> Result<K, &'static str>;
781
782 /// Add a `str` input to a symbol list while enumerating the character array internally.
783 /// Returns a pointer to the (potentially reallocated) `K` object.
784 /// # Example
785 /// ```no_run
786 /// use kdbplus::api::*;
787 /// use kdbplus::qtype;
788 ///
789 /// #[no_mangle]
790 /// pub extern "C" fn create_symbol_list2(_: K) -> K{
791 /// let mut list=new_list(qtype::SYMBOL_LIST, 0);
792 /// list.push_symbol("Abraham").unwrap();
793 /// list.push_symbol("Isaac").unwrap();
794 /// list.push_symbol("Jacob").unwrap();
795 /// list.push_symbol_n("Josephine", 6).unwrap();
796 /// list
797 /// }
798 /// ```
799 /// ```q
800 /// q)summon:`libapi_examples 2: (`create_symbol_list2; 1)
801 /// q)summon[]
802 /// `Abraham`Isaac`Jacob`Joseph
803 /// q)`Abraham`Isaac`Jacob`Joseph ~ summon[]
804 /// 1b
805 /// ```
806 /// # Note
807 /// In this example we did not allocate an array as `new_list(qtype::SYMBOL_LIST as I, 0)` to use `push_symbol`.
808 /// As `new_list` initializes the internal list size `n` with its argument, preallocating memory with `new_list`
809 /// and then using `push_symbol` will crash. If you want to allocate a memory in advance, you can substitute a value
810 /// after converting the q list object into a slice with [`as_mut_slice`](trait.KUtility.html#tymethod.as_mut_slice).
811 fn push_symbol(&mut self, symbol: &str) -> Result<K, &'static str>;
812
813 /// Add the first `n` characters of a `str` input to a symbol list while enumerating the character array internally.
814 /// Returns a pointer to the (potentially reallocated) `K` object.
815 /// # Example
816 /// See the example of [`push_symbol`](#fn.push_symbol).
817 fn push_symbol_n(&mut self, symbol: &str, n: I) -> Result<K, &'static str>;
818
819 /// Get the length of q object. The meaning of the returned value varies according to the type:
820 /// - atom: 1
821 /// - list: The number of elements in the list.
822 /// - table: The number of rows.
823 /// - dictionary: The number of keys.
824 /// - general null: 1
825 /// # Example
826 /// ```no_run
827 /// use kdbplus::api::*;
828 ///
829 /// #[no_mangle]
830 /// pub extern "C" fn numbers(obj: K) -> K{
831 /// let count=format!("{} people are in numbers", obj.len());
832 /// new_string(&count)
833 /// }
834 /// ```
835 /// ```q
836 /// q)census: `libapi_examples 2: (`numbers; 1);
837 /// q)census[(::)]
838 /// "1 people are in numbers"
839 /// q)census[til 4]
840 /// "4 people are in numbers"
841 /// q)census[`a`b!("many"; `split`asunder)]
842 /// "2 people are in numbers"
843 /// q)census[([] id: til 1000)]
844 /// "1000 people are in numbers"
845 /// ```
846 fn len(&self) -> i64;
847
848 /// Get a type of `K` object.
849 fn get_type(&self) -> i8;
850
851 /// Set a type of `K` object.
852 /// # Example
853 /// See the example of [`load_as_q_function](fn.load_as_q_function.html).
854 fn set_type(&mut self, qtype: i8);
855
856 /// Set an attribute to q list object.
857 /// # Example
858 /// ```no_run
859 /// use kdbplus::qattribute;
860 /// use kdbplus::api::*;
861 ///
862 /// #[no_mangle]
863 /// pub extern "C" fn labeling(mut list: K) -> K{
864 /// match list.set_attribute(qattribute::SORTED){
865 /// Ok(_) => increment_reference_count(list),
866 /// Err(error) => new_error(error)
867 /// }
868 /// }
869 /// ```
870 /// ```q
871 /// q)setter: `libapi_examples.so (`labeling; 1);
872 /// q)setter 1 2 3
873 /// `s#1 2 3
874 /// q)setter 777
875 /// 'not a simple list
876 /// ```
877 /// # Note
878 /// q does NOT validate the attribute. Wrong attribute can lead to suboptimal behavior or application crash if
879 /// you are unfortunate.
880 fn set_attribute(&mut self, attribute: i8) -> Result<(), &'static str>;
881
882 /// Serialize q object and return serialized q byte list object on success: otherwise null.
883 /// Mode is either of:
884 /// - -1: Serialize within the same process.
885 /// - 1: retain enumerations, allow serialization of timespan and timestamp: Useful for passing data between threads
886 /// - 2: unenumerate, allow serialization of timespan and timestamp
887 /// - 3: unenumerate, compress, allow serialization of timespan and timestamp
888 /// # Example
889 /// ```no_run
890 /// use kdbplus::api::*;
891 ///
892 /// #[no_mangle]
893 /// pub extern "C" fn encrypt(object: K)->K{
894 /// match object.q_ipc_encode(3){
895 /// Ok(bytes) => bytes,
896 /// Err(error) => new_error(error)
897 /// }
898 /// }
899 /// ```
900 /// ```q
901 /// q)disguise: `libapi_examples 2: (`encrypt; 1);
902 /// q)list: (til 3; "abc"; 2018.02.18D04:30:00.000000000; `revive);
903 /// q)disguise list
904 /// 0x010000004600000000000400000007000300000000000000000000000100000000000000020..
905 /// ```
906 fn q_ipc_encode(&self, mode: I) -> Result<K, &'static str>;
907
908 /// Deserialize a bytes into q object.
909 /// # Example
910 /// ```no_run
911 /// use kdbplus::api::*;
912 ///
913 /// #[no_mangle]
914 /// pub extern "C" fn decrypt(bytes: K)->K{
915 /// match bytes.q_ipc_decode(){
916 /// Ok(object) => object,
917 /// Err(error) => new_error(error)
918 /// }
919 /// }
920 /// ```
921 /// ```q
922 /// q)uncover: `libapi_examples 2: (`decrypt; 1);
923 /// q)uncover -8!"What is the purpose of CREATION?"
924 /// "What is the purpose of CREATION?"
925 /// ```
926 fn q_ipc_decode(&self) -> Result<K, &'static str>;
927}
928
929//++++++++++++++++++++++++++++++++++++++++++++++++++//
930// >> Implementation
931//++++++++++++++++++++++++++++++++++++++++++++++++++//
932
933//%% U %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
934
935impl U {
936 /// Create 16-byte GUID object.
937 pub fn new(guid: [u8; 16]) -> Self {
938 U { guid }
939 }
940}
941
942//%% K %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
943
944unsafe impl Send for k0_inner {}
945unsafe impl Send for k0 {}
946
947impl KUtility for K {
948 #[inline]
949 fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
950 unsafe {
951 std::slice::from_raw_parts_mut(
952 (*self).value.list.G0.as_mut_ptr() as *mut T,
953 (*self).value.list.n as usize,
954 )
955 }
956 }
957
958 fn get_row(&self, index: usize, enum_sources: &[&str]) -> Result<K, &'static str> {
959 match unsafe { (**self).qtype } {
960 qtype::TABLE => {
961 let keys = unsafe { (**self).value.table }.as_mut_slice::<K>()[0];
962 let values = unsafe { (**self).value.table }.as_mut_slice::<K>()[1];
963 if (unsafe { (*values.as_mut_slice::<K>()[0]).value.list }.n as usize) < index + 1 {
964 // Index out of bounds
965 Err("index out of bounds\0")
966 } else {
967 let num_columns = unsafe { (*keys).value.list }.n;
968 let row = new_list(qtype::COMPOUND_LIST, num_columns);
969 let row_slice = row.as_mut_slice::<K>();
970 let mut enum_source_index = 0;
971 for (i, column) in values.as_mut_slice::<K>().iter().enumerate() {
972 match column.get_type() {
973 qtype::BOOL_LIST => {
974 row_slice[i] = new_bool(column.as_mut_slice::<G>()[index] as i32);
975 }
976 qtype::BYTE_LIST => {
977 row_slice[i] = new_byte(column.as_mut_slice::<G>()[index] as i32);
978 }
979 qtype::SHORT_LIST => {
980 row_slice[i] = new_short(column.as_mut_slice::<H>()[index] as i32);
981 }
982 qtype::INT_LIST => {
983 row_slice[i] = new_int(column.as_mut_slice::<I>()[index]);
984 }
985 qtype::LONG_LIST => {
986 row_slice[i] = new_long(column.as_mut_slice::<J>()[index]);
987 }
988 qtype::REAL_LIST => {
989 row_slice[i] = new_real(column.as_mut_slice::<E>()[index] as f64);
990 }
991 qtype::FLOAT_LIST => {
992 row_slice[i] = new_float(column.as_mut_slice::<F>()[index]);
993 }
994 qtype::STRING => {
995 row_slice[i] = new_char(column.as_mut_slice::<G>()[index] as char);
996 }
997 qtype::SYMBOL_LIST => {
998 row_slice[i] =
999 new_symbol(S_to_str(column.as_mut_slice::<S>()[index]));
1000 }
1001 qtype::TIMESTAMP_LIST => {
1002 row_slice[i] = new_timestamp(column.as_mut_slice::<J>()[index]);
1003 }
1004 qtype::MONTH_LIST => {
1005 row_slice[i] = new_month(column.as_mut_slice::<I>()[index]);
1006 }
1007 qtype::DATE_LIST => {
1008 row_slice[i] = new_date(column.as_mut_slice::<I>()[index]);
1009 }
1010 qtype::DATETIME_LIST => {
1011 row_slice[i] = new_datetime(column.as_mut_slice::<F>()[index]);
1012 }
1013 qtype::TIMESPAN_LIST => {
1014 row_slice[i] = new_timespan(column.as_mut_slice::<J>()[index]);
1015 }
1016 qtype::MINUTE_LIST => {
1017 row_slice[i] = new_minute(column.as_mut_slice::<I>()[index]);
1018 }
1019 qtype::SECOND_LIST => {
1020 row_slice[i] = new_second(column.as_mut_slice::<I>()[index]);
1021 }
1022 qtype::TIME_LIST => {
1023 row_slice[i] = new_time(column.as_mut_slice::<I>()[index]);
1024 }
1025 qtype::ENUM_LIST => {
1026 if enum_sources.len() <= enum_source_index {
1027 // Index out of bounds
1028 decrement_reference_count(row);
1029 return Err("insufficient enum sources\0");
1030 }
1031 let enum_value = new_enum(
1032 enum_sources[enum_source_index],
1033 column.as_mut_slice::<J>()[index],
1034 );
1035 if unsafe { (*enum_value).qtype } == qtype::ERROR {
1036 // Error in creating enum object.
1037 decrement_reference_count(row);
1038 let error = S_to_str(unsafe { (*enum_value).value.symbol });
1039 decrement_reference_count(enum_value);
1040 return Err(error);
1041 } else {
1042 row_slice[i] = enum_value;
1043 enum_source_index += 1;
1044 }
1045 }
1046 qtype::COMPOUND_LIST => {
1047 // Increment reference count since compound list consumes the element.
1048 row_slice[i] =
1049 increment_reference_count(column.as_mut_slice::<K>()[index]);
1050 }
1051 // There are no other list type
1052 _ => unreachable!(),
1053 }
1054 }
1055 Ok(new_dictionary(increment_reference_count(keys), row))
1056 }
1057 }
1058 _ => Err("not a table\0"),
1059 }
1060 }
1061
1062 #[inline]
1063 fn get_bool(&self) -> Result<bool, &'static str> {
1064 match unsafe { (**self).qtype } {
1065 qtype::BOOL_ATOM => Ok(unsafe { (**self).value.byte != 0 }),
1066 _ => Err("not a bool\0"),
1067 }
1068 }
1069
1070 #[inline]
1071 fn get_guid(&self) -> Result<[u8; 16], &'static str> {
1072 match unsafe { (**self).qtype } {
1073 qtype::GUID_ATOM => {
1074 Ok(
1075 unsafe { std::slice::from_raw_parts((**self).value.list.G0.as_ptr(), 16) }
1076 .try_into()
1077 .unwrap(),
1078 )
1079 }
1080 _ => Err("not a GUID\0"),
1081 }
1082 }
1083
1084 #[inline]
1085 fn get_byte(&self) -> Result<u8, &'static str> {
1086 match unsafe { (**self).qtype } {
1087 qtype::BYTE_ATOM => Ok(unsafe { (**self).value.byte }),
1088 _ => Err("not a byte\0"),
1089 }
1090 }
1091
1092 #[inline]
1093 fn get_short(&self) -> Result<i16, &'static str> {
1094 match unsafe { (**self).qtype } {
1095 qtype::SHORT_ATOM => Ok(unsafe { (**self).value.short }),
1096 _ => Err("not a short\0"),
1097 }
1098 }
1099
1100 #[inline]
1101 fn get_int(&self) -> Result<i32, &'static str> {
1102 match unsafe { (**self).qtype } {
1103 qtype::INT_ATOM
1104 | qtype::MONTH_ATOM
1105 | qtype::DATE_ATOM
1106 | qtype::MINUTE_ATOM
1107 | qtype::SECOND_ATOM
1108 | qtype::TIME_ATOM => Ok(unsafe { (**self).value.int }),
1109 _ => Err("not an int\0"),
1110 }
1111 }
1112
1113 #[inline]
1114 fn get_long(&self) -> Result<i64, &'static str> {
1115 match unsafe { (**self).qtype } {
1116 qtype::LONG_ATOM | qtype::TIMESTAMP_ATOM | qtype::TIMESPAN_ATOM | qtype::ENUM_ATOM => {
1117 Ok(unsafe { (**self).value.long })
1118 }
1119 _ => Err("not a long\0"),
1120 }
1121 }
1122
1123 #[inline]
1124 fn get_real(&self) -> Result<f32, &'static str> {
1125 match unsafe { (**self).qtype } {
1126 qtype::REAL_ATOM => Ok(unsafe { (**self).value.real }),
1127 _ => Err("not a real\0"),
1128 }
1129 }
1130
1131 #[inline]
1132 fn get_float(&self) -> Result<f64, &'static str> {
1133 match unsafe { (**self).qtype } {
1134 qtype::FLOAT_ATOM | qtype::DATETIME_ATOM => Ok(unsafe { (**self).value.float }),
1135 _ => Err("not a float\0"),
1136 }
1137 }
1138
1139 #[inline]
1140 fn get_char(&self) -> Result<char, &'static str> {
1141 match unsafe { (**self).qtype } {
1142 qtype::CHAR => Ok(unsafe { (**self).value.byte as char }),
1143 _ => Err("not a char\0"),
1144 }
1145 }
1146
1147 #[inline]
1148 fn get_symbol(&self) -> Result<&str, &'static str> {
1149 match unsafe { (**self).qtype } {
1150 qtype::SYMBOL_ATOM => Ok(S_to_str(unsafe { (**self).value.symbol })),
1151 _ => Err("not a symbol\0"),
1152 }
1153 }
1154
1155 #[inline]
1156 fn get_str(&self) -> Result<&str, &'static str> {
1157 match unsafe { (**self).qtype } {
1158 qtype::STRING => Ok(unsafe { str::from_utf8_unchecked_mut(self.as_mut_slice::<G>()) }),
1159 _ => Err("not a string\0"),
1160 }
1161 }
1162
1163 #[inline]
1164 fn get_string(&self) -> Result<String, &'static str> {
1165 match unsafe { (**self).qtype } {
1166 qtype::STRING => {
1167 Ok(unsafe { String::from_utf8_unchecked(self.as_mut_slice::<G>().to_vec()) })
1168 }
1169 _ => Err("not a string\0"),
1170 }
1171 }
1172
1173 #[inline]
1174 fn get_dictionary(&self) -> Result<K, &'static str> {
1175 match unsafe { (**self).qtype } {
1176 qtype::TABLE => Ok(unsafe { (**self).value.table }),
1177 _ => Err("not a table\0"),
1178 }
1179 }
1180
1181 #[inline]
1182 fn get_error_string(&self) -> Result<&str, &'static str> {
1183 match unsafe { (**self).qtype } {
1184 qtype::ERROR => {
1185 if !unsafe { (**self).value.symbol }.is_null() {
1186 Ok(S_to_str(unsafe { (**self).value.symbol }))
1187 } else {
1188 Err("not an error\0")
1189 }
1190 }
1191 _ => Err("not an error\0"),
1192 }
1193 }
1194
1195 #[inline]
1196 fn get_attribute(&self) -> i8 {
1197 unsafe { (**self).attribute }
1198 }
1199
1200 #[inline]
1201 fn get_refcount(&self) -> i32 {
1202 unsafe { (**self).refcount }
1203 }
1204
1205 #[inline]
1206 fn append(&mut self, list: K) -> Result<K, &'static str> {
1207 if unsafe { (**self).qtype } >= 0 && unsafe { (**self).qtype } == unsafe { (*list).qtype } {
1208 let result = Ok(unsafe { native::jv(self, list) });
1209 // Free appended list for internally created object.
1210 unsafe { native::r0(list) };
1211 result
1212 } else {
1213 Err("not a list or types do not match\0")
1214 }
1215 }
1216
1217 #[inline]
1218 fn push(&mut self, atom: K) -> Result<K, &'static str> {
1219 match unsafe { (**self).qtype } {
1220 qtype::COMPOUND_LIST => Ok(unsafe { native::jk(self, atom) }),
1221 _ => Err("not a list or types do not match\0"),
1222 }
1223 }
1224
1225 #[inline]
1226 fn push_raw<T>(&mut self, mut atom: T) -> Result<K, &'static str> {
1227 match unsafe { (**self).qtype } {
1228 _t @ qtype::BOOL_LIST..=qtype::ENUM_LIST => {
1229 Ok(unsafe { native::ja(self, std::mem::transmute::<*mut T, *mut V>(&mut atom)) })
1230 }
1231 _ => Err("not a simple list or types do not match\0"),
1232 }
1233 }
1234
1235 #[inline]
1236 fn push_symbol(&mut self, symbol: &str) -> Result<K, &'static str> {
1237 match unsafe { (**self).qtype } {
1238 qtype::SYMBOL_LIST => Ok(unsafe { native::js(self, native::ss(str_to_S!(symbol))) }),
1239 _ => Err("not a symbol list\0"),
1240 }
1241 }
1242
1243 #[inline]
1244 fn push_symbol_n(&mut self, symbol: &str, n: I) -> Result<K, &'static str> {
1245 match unsafe { (**self).qtype } {
1246 qtype::SYMBOL_LIST => Ok(unsafe { native::js(self, native::sn(str_to_S!(symbol), n)) }),
1247 _ => Err("not a symbol list or types do not match\0"),
1248 }
1249 }
1250
1251 #[inline]
1252 fn len(&self) -> i64 {
1253 match unsafe { (**self).qtype } {
1254 _t @ qtype::ENUM_ATOM..=qtype::BOOL_ATOM => {
1255 // Atom
1256 1
1257 }
1258 _t @ qtype::COMPOUND_LIST..=qtype::ENUM_LIST => {
1259 // List
1260 unsafe { (**self).value.list }.n
1261 }
1262 qtype::TABLE => {
1263 // Table
1264 // Access underlying table (dictionary structure) and retrieve values of the dictionary.
1265 // The values (columns) is assured to be a list of lists as it is a table. so cast it to list of `K`.
1266 // Size of the table is a length of the first column.
1267 unsafe {
1268 (*((**self).value.table).as_mut_slice::<K>()[1].as_mut_slice::<K>()[0])
1269 .value
1270 .list
1271 }
1272 .n
1273 }
1274 qtype::DICTIONARY | qtype::SORTED_DICTIONARY => {
1275 // Dictionary
1276 // Access to keys of the dictionary and retrieve its length.
1277 unsafe { (*(*self).as_mut_slice::<K>()[0]).value.list }.n
1278 }
1279 _ => {
1280 // General null, function, foreign
1281 1
1282 }
1283 }
1284 }
1285
1286 #[inline]
1287 fn get_type(&self) -> i8 {
1288 unsafe { (**self).qtype }
1289 }
1290
1291 #[inline]
1292 fn set_type(&mut self, qtype: i8) {
1293 unsafe { (**self).qtype = qtype };
1294 }
1295
1296 #[inline]
1297 fn set_attribute(&mut self, attribute: i8) -> Result<(), &'static str> {
1298 match unsafe { (**self).qtype } {
1299 _t @ qtype::BOOL_LIST..=qtype::TIME_LIST => {
1300 unsafe { (**self).attribute = attribute };
1301 Ok(())
1302 }
1303 _ => Err("not a simple list\0"),
1304 }
1305 }
1306
1307 #[inline]
1308 fn q_ipc_encode(&self, mode: I) -> Result<K, &'static str> {
1309 let result = error_to_string(unsafe { native::b9(mode, *self) });
1310 match unsafe { (*result).qtype } {
1311 qtype::ERROR => {
1312 decrement_reference_count(result);
1313 Err("failed to encode\0")
1314 }
1315 _ => Ok(result),
1316 }
1317 }
1318
1319 #[inline]
1320 fn q_ipc_decode(&self) -> Result<K, &'static str> {
1321 match unsafe { (**self).qtype } {
1322 qtype::BYTE_LIST => {
1323 let result = error_to_string(unsafe { native::d9(*self) });
1324 match unsafe { (*result).qtype } {
1325 qtype::ERROR => {
1326 decrement_reference_count(result);
1327 Err("failed to decode\0")
1328 }
1329 _ => Ok(result),
1330 }
1331 }
1332 _ => Err("not bytes\0"),
1333 }
1334 }
1335}
1336
1337impl k0 {
1338 /// Derefer `k0` as a mutable slice. For supported types, see [`as_mut_slice`](trait.KUtility.html#tymethod.as_mut_slice).
1339 /// # Note
1340 /// Used if `K` needs to be sent to another thread. `K` cannot implement `Send` and therefore
1341 /// its inner struct must be sent instead.
1342 /// # Example
1343 /// See the example of [`setm`](native/fn.setm.html).
1344 #[inline]
1345 pub fn as_mut_slice<'a, T>(&mut self) -> &'a mut [T] {
1346 unsafe {
1347 std::slice::from_raw_parts_mut(
1348 self.value.list.G0.as_mut_ptr() as *mut T,
1349 self.value.list.n as usize,
1350 )
1351 }
1352 }
1353}
1354
1355//++++++++++++++++++++++++++++++++++++++++++++++++++//
1356// >> Utility
1357//++++++++++++++++++++++++++++++++++++++++++++++++++//
1358
1359//%% Utility %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1360
1361/// Convert `S` to `&str`. This function is intended to convert symbol type (null-terminated char-array) to `str`.
1362/// # Extern
1363/// ```no_run
1364/// use kdbplus::*;
1365/// use kdbplus::api::*;
1366///
1367/// #[no_mangle]
1368/// pub extern "C" fn print_symbol(symbol: K) -> K{
1369/// unsafe{
1370/// if (*symbol).qtype == qtype::SYMBOL_ATOM{
1371/// println!("symbol: `{}", S_to_str((*symbol).value.symbol));
1372/// }
1373/// // return null
1374/// KNULL
1375/// }
1376/// }
1377/// ```
1378/// ```q
1379/// q)print_symbol:`libapi_examples 2: (`print_symbol; 1)
1380/// q)a:`kx
1381/// q)print_symbol a
1382/// symbol: `kx
1383/// ```
1384#[inline]
1385pub fn S_to_str<'a>(cstring: S) -> &'a str {
1386 unsafe { CStr::from_ptr(cstring).to_str().unwrap() }
1387}
1388
1389/// Convert null-terminated `&str` to `S`.
1390/// # Example
1391/// ```no_run
1392/// use kdbplus::api::*;
1393///
1394/// #[no_mangle]
1395/// pub extern "C" fn pingpong2(_: K) -> K{
1396/// unsafe{native::k(0, null_terminated_str_to_S("ping\0"), new_int(77), KNULL)}
1397/// }
1398/// ```
1399/// ```q
1400/// q)ping:{[int] `$string[int], "_pong!!"};
1401/// q)pingpong: `libapi_examples 2: (`pingpong2; 1);
1402/// q)pingpong[]
1403/// `77_pong!!
1404/// ```
1405#[inline]
1406pub fn null_terminated_str_to_S(string: &str) -> S {
1407 unsafe { CStr::from_bytes_with_nul_unchecked(string.as_bytes()).as_ptr() as S }
1408}
1409
1410/// Convert null terminated `&str` into `const_S`. Expected usage is to build
1411/// a q error object with `krr`.
1412/// # Example
1413/// ```no_run
1414/// use kdbplus::api::*;
1415/// use kdbplus::api::native::*;
1416/// use kdbplus::qtype;
1417///
1418/// pub extern "C" fn must_be_int2(obj: K) -> K{
1419/// unsafe{
1420/// if (*obj).qtype != qtype::INT_ATOM{
1421/// krr(null_terminated_str_to_const_S("not an int\0"))
1422/// }
1423/// else{
1424/// KNULL
1425/// }
1426/// }
1427/// }
1428/// ```
1429/// ```q
1430/// q)check:`libapi_examples 2: (`must_be_int; 1)
1431/// q)a:100
1432/// q)check a
1433/// 'not an int
1434/// [0] check a
1435/// ^
1436/// q)a:42i
1437/// q)check a
1438/// ```
1439pub fn null_terminated_str_to_const_S(string: &str) -> const_S {
1440 string.as_bytes().as_ptr() as const_S
1441}
1442
1443//++++++++++++++++++++++++++++++++++++++++++++++++++//
1444// >> Re-export
1445//++++++++++++++++++++++++++++++++++++++++++++++++++//
1446
1447//%% Constructor %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1448
1449/// Constructor of q bool object. Relabeling of `kb`.
1450/// # Example
1451/// ```no_run
1452/// use kdbplus::api::*;
1453///
1454/// #[no_mangle]
1455/// pub extern "C" fn create_bool(_: K) -> K{
1456/// new_bool(0)
1457/// }
1458/// ```
1459/// ```q
1460/// q)no: `libapi_examples 2: (`create_bool; 1);
1461/// q)no[]
1462/// 0b
1463/// ```
1464#[inline]
1465pub fn new_bool(boolean: I) -> K {
1466 unsafe { native::kb(boolean) }
1467}
1468
1469/// Constructor of q GUID object. Relabeling of `ku`.
1470/// # Example
1471/// ```no_run
1472/// use kdbplus::api::*;
1473///
1474/// #[no_mangle]
1475/// pub extern "C" fn create_guid(_: K) -> K{
1476/// new_guid([0x1e_u8, 0x11, 0x17, 0x0c, 0x42, 0x24, 0x25, 0x2c, 0x1c, 0x14, 0x1e, 0x22, 0x4d, 0x3d, 0x46, 0x24])
1477/// }
1478/// ```
1479/// ```q
1480/// q)create_guid: `libapi_examples 2: (`create_guid; 1);
1481/// q)create_guid[]
1482/// 1e11170c-4224-252c-1c14-1e224d3d4624
1483/// ```
1484#[inline]
1485pub fn new_guid(guid: [G; 16]) -> K {
1486 unsafe { native::ku(U::new(guid)) }
1487}
1488
1489/// Constructor of q byte object. Relabeling of `kg`.
1490/// # Example
1491/// ```no_run
1492/// use kdbplus::api::*;
1493///
1494/// #[no_mangle]
1495/// pub extern "C" fn create_byte(_: K) -> K{
1496/// new_byte(0x3c)
1497/// }
1498/// ```
1499/// ```q
1500/// q)create_byte: `libapi_examples 2: (`create_byte; 1);
1501/// q)create_byte[]
1502/// 0x3c
1503/// ```
1504#[inline]
1505pub fn new_byte(byte: I) -> K {
1506 unsafe { native::kg(byte) }
1507}
1508
1509/// Constructor of q short object. Relabeling of `kh`.
1510/// # Example
1511/// ```no_run
1512/// use kdbplus::api::*;
1513///
1514/// #[no_mangle]
1515/// pub extern "C" fn create_short(_: K) -> K{
1516/// new_short(-144)
1517/// }
1518/// ```
1519/// ```q
1520/// q)shortage: `libapi_examples 2: (`create_short; 1);
1521/// q)shortage[]
1522/// -144h
1523/// ```
1524#[inline]
1525pub fn new_short(short: I) -> K {
1526 unsafe { native::kh(short) }
1527}
1528
1529/// Constructor of q int object. Relabeling of `ki`.
1530/// # Example
1531/// ```no_run
1532/// use kdbplus::api::*;
1533///
1534/// #[no_mangle]
1535/// pub extern "C" fn create_int(_: K) -> K{
1536/// new_int(86400000)
1537/// }
1538/// ```
1539/// ```q
1540/// q)trvial: `libapi_examples 2: (`create_int; 1);
1541/// q)trivial[]
1542/// 86400000i
1543/// ```
1544#[inline]
1545pub fn new_int(int: I) -> K {
1546 unsafe { native::ki(int) }
1547}
1548
1549/// Constructor of q long object. Relabeling of `kj`.
1550/// # Example
1551/// ```no_run
1552/// use kdbplus::api::*;
1553///
1554/// #[no_mangle]
1555/// pub extern "C" fn create_long(_: K) -> K{
1556/// new_long(-668541276001729000)
1557/// }
1558/// ```
1559/// ```q
1560/// q)lengthy: `libapi_examples 2: (`create_long; 1);
1561/// q)lengthy[]
1562/// -668541276001729000
1563/// ```
1564#[inline]
1565pub fn new_long(long: J) -> K {
1566 unsafe { native::kj(long) }
1567}
1568
1569/// Constructor of q real object. Relabeling of `ke`.
1570/// # Example
1571/// ```no_run
1572/// use kdbplus::api::*;
1573///
1574/// #[no_mangle]
1575/// pub extern "C" fn create_real(_: K) -> K{
1576/// new_real(0.00324)
1577/// }
1578/// ```
1579/// ```q
1580/// q)reality: `libapi_examples 2: (`create_real; 1);
1581/// q)reality[]
1582/// 0.00324e
1583/// ```
1584#[inline]
1585pub fn new_real(real: F) -> K {
1586 unsafe { native::ke(real) }
1587}
1588
1589/// Constructor of q float object. Relabeling of `kf`.
1590/// # Example
1591/// ```
1592/// use kdbplus::api::*;
1593///
1594/// #[no_mangle]
1595/// pub extern "C" fn create_float(_: K) -> K{
1596/// new_float(-6302.620)
1597/// }
1598/// ```
1599/// ```q
1600/// q)coffee_float: `libapi_examples 2: (`create_float; 1);
1601/// q)coffee_float[]
1602/// -6302.62
1603/// ```
1604#[inline]
1605pub fn new_float(float: F) -> K {
1606 unsafe { native::kf(float) }
1607}
1608
1609/// Constructor of q char object. Relabeling of `kc`.
1610/// # Example
1611/// ```no_run
1612/// use kdbplus::api::*;
1613///
1614/// #[no_mangle]
1615/// pub extern "C" fn create_char2(_: K) -> K{
1616/// new_char('t')
1617/// }
1618/// ```
1619/// ```q
1620/// q)heavy: `libapi_examples 2: (`create_char2; 1);
1621/// q)heavy[]
1622/// "t"
1623/// ```
1624#[inline]
1625pub fn new_char(character: char) -> K {
1626 unsafe { native::kc(character as I) }
1627}
1628
1629/// Constructor of q symbol object. Relabeling of `ks`.
1630/// # Example
1631/// ```no_run
1632/// use kdbplus::api::*;
1633///
1634/// #[no_mangle]
1635/// pub extern "C" fn create_symbol2(_: K) -> K{
1636/// new_symbol("symbolic")
1637/// }
1638/// ```
1639/// ```q
1640/// q)hard: `libapi_examples 2: (`create_symbol2; 1);
1641/// q)hard[]
1642/// `symbolic
1643/// q)`symbolic ~ hard[]
1644/// 1b
1645/// ```
1646#[inline]
1647pub fn new_symbol(symbol: &str) -> K {
1648 unsafe { native::ks(str_to_S!(symbol)) }
1649}
1650
1651/// Constructor of q timestamp from elapsed time in nanoseconds since kdb+ epoch (`2000.01.01`). Relabeling of `ktj`.
1652/// ```no_run
1653/// use kdbplus::api::*;
1654///
1655/// #[no_mangle]
1656/// pub extern "C" fn create_timestamp2(_: K) -> K{
1657/// // 2015.03.16D00:00:00:00.000000000
1658/// new_timestamp(479779200000000000)
1659/// }
1660/// ```
1661/// ```q
1662/// q)stamp: `libapi_examples 2: (`create_timestamp2; 1);
1663/// q)stamp[]
1664/// 2015.03.16D00:00:00.000000000
1665/// ```
1666#[inline]
1667pub fn new_timestamp(nanoseconds: J) -> K {
1668 unsafe { native::ktj(qtype::TIMESTAMP_ATOM as I, nanoseconds) }
1669}
1670
1671/// Create a month object from the number of months since kdb+ epoch (`2000.01.01`).
1672/// This is a complememtal constructor of missing month type.
1673/// # Example
1674/// ```no_run
1675/// use kdbplus::api::*;
1676///
1677/// #[no_mangle]
1678/// pub extern "C" fn create_month(_: K) -> K{
1679/// // 2010.07m
1680/// new_month(126)
1681/// }
1682/// ```
1683/// ```q
1684/// q)create_month: `libapi_examples 2: (`create_month; 1);
1685/// q)create_month[]
1686/// 2010.07m
1687/// ```
1688#[inline]
1689pub fn new_month(months: I) -> K {
1690 unsafe {
1691 let month = native::ka(qtype::MONTH_ATOM as I);
1692 (*month).value.int = months;
1693 month
1694 }
1695}
1696
1697/// Constructor of q date object. Relabeling of `kd`.
1698/// # Example
1699/// ```no_run
1700/// use kdbplus::api::*;
1701///
1702/// #[no_mangle]
1703/// pub extern "C" fn create_date(_: K) -> K{
1704/// // 1999.12.25
1705/// new_date(-7)
1706/// }
1707/// ```
1708/// ```q
1709/// q)nostradamus: `libapi_examples 2: (`create_date; 1);
1710/// q)nostradamus[]
1711/// 1999.12.25
1712/// ```
1713#[inline]
1714pub fn new_date(days: I) -> K {
1715 unsafe { native::kd(days) }
1716}
1717
1718/// Constructor of q datetime object from the number of days since kdb+ epoch (`2000.01.01`). Relabeling of `kz`.
1719/// ```no_run
1720/// use kdbplus::api::*;
1721///
1722/// #[no_mangle]
1723/// pub extern "C" fn create_datetime(_: K) -> K{
1724/// // 2015.03.16T12:00:00:00.000
1725/// new_datetime(5553.5)
1726/// }
1727/// ```
1728/// ```q
1729/// q)omega_date: libc_api_examples 2: (`create_datetime; 1);
1730/// q)omega_date[]
1731/// 2015.03.16T12:00:00.000
1732/// ```
1733#[inline]
1734pub fn new_datetime(days: F) -> K {
1735 unsafe { native::kz(days) }
1736}
1737
1738/// Constructor of q timespan object from nanoseconds. Relabeling of `ktj`.
1739/// ```no_run
1740/// use kdbplus::api::*;
1741///
1742/// #[no_mangle]
1743/// pub extern "C" fn create_timespan2(_: K) -> K{
1744/// // -1D01:30:00.001234567
1745/// new_timespan(-91800001234567)
1746/// }
1747/// ```
1748/// ```q
1749/// q)duration: libc_api_examples 2: (`create_timespan2; 1);
1750/// q)duration[]
1751/// -1D01:30:00.001234567
1752/// ```
1753#[inline]
1754pub fn new_timespan(nanoseconds: J) -> K {
1755 unsafe { native::ktj(qtype::TIMESPAN_ATOM as I, nanoseconds) }
1756}
1757
1758/// Create a month object. This is a complememtal constructor of
1759/// missing minute type.
1760/// # Example
1761/// ```no_run
1762/// use kdbplus::api::*;
1763///
1764/// #[no_mangle]
1765/// pub extern "C" fn create_minute(_: K) -> K{
1766/// // 10:40
1767/// new_minute(640)
1768/// }
1769/// ```
1770/// ```q
1771/// q)minty: `libapi_examples 2: (`create_minute; 1);
1772/// q)minty[]
1773/// 10:40
1774/// ```
1775#[inline]
1776pub fn new_minute(minutes: I) -> K {
1777 unsafe {
1778 let minute = native::ka(qtype::MINUTE_ATOM as I);
1779 (*minute).value.int = minutes;
1780 minute
1781 }
1782}
1783
1784/// Create a month object. This is a complememtal constructor of
1785/// missing second type.
1786/// # Example
1787/// ```no_run
1788/// use kdbplus::api::*;
1789///
1790/// #[no_mangle]
1791/// pub extern "C" fn create_second(_: K) -> K{
1792/// // -02:00:00
1793/// new_second(-7200)
1794/// }
1795/// ```
1796/// ```q
1797/// q)third: `libapi_examples 2: (`create_second; 1);
1798/// q)third[]
1799/// -02:00:00
1800/// ```
1801#[inline]
1802pub fn new_second(seconds: I) -> K {
1803 unsafe {
1804 let second = native::ka(qtype::SECOND_ATOM as I);
1805 (*second).value.int = seconds;
1806 second
1807 }
1808}
1809
1810/// Constructor of q time object. Relabeling of `kt`.
1811/// # Example
1812/// ```no_run
1813/// use kdbplus::api::*;
1814///
1815/// #[no_mangle]
1816/// pub extern "C" fn create_time(_: K) -> K{
1817/// // -01:30:00.123
1818/// new_time(-5400123)
1819/// }
1820/// ```
1821/// ```q
1822/// q)ancient: libc_api_examples 2: (`create_time; 1);
1823/// q)ancient[]
1824/// -01:30:00.123
1825/// ```
1826#[inline]
1827pub fn new_time(milliseconds: I) -> K {
1828 unsafe { native::kt(milliseconds) }
1829}
1830
1831/// Constructor of q enum object. This is a complememtal constructor of
1832/// missing second type.
1833/// # Example
1834/// ```no_run
1835/// use kdbplus::api::*;
1836///
1837/// #[no_mangle]
1838/// pub extern "C" fn create_enum(source: K, index: K) -> K{
1839/// // Error if the specified enum source does not exist or it is not a symbol list or the index is out of enum range
1840/// new_enum(source.get_str().unwrap(), index.get_long().unwrap())
1841/// }
1842/// ```
1843/// ```q
1844/// q)enumerate: libc_api_examples 2: (`create_enum; 2);
1845/// q)sym: `a`b`c
1846/// q)enumerate["sym"; 1]
1847/// `sym$`b
1848/// q)enumerate["sym"; 3]
1849/// 'index out of enum range
1850/// [0] enumerate["sym"; 3]
1851/// ^
1852/// q)enumerate["som"; 0]
1853/// 'som
1854/// [1] som
1855/// ^
1856/// q))\
1857/// q)som:til 3
1858/// q)enumerate["som"; 0]
1859/// 'enum must be cast to symbol list
1860/// [0] enumerate["som"; 0]
1861/// ^
1862/// q)som:`a`b
1863/// q)enumerate["som"; 0]
1864/// `som$`a
1865/// ```
1866#[inline]
1867pub fn new_enum(source: &str, index: J) -> K {
1868 let sym = unsafe { native::k(0, str_to_S!(source), KNULL) };
1869 if unsafe { (*sym).qtype } == qtype::ERROR {
1870 // Error. Specified sym does not exist
1871 sym
1872 } else if unsafe { (*sym).qtype } != qtype::SYMBOL_LIST {
1873 // sym is not a symbol list
1874 unsafe {
1875 native::r0(sym);
1876 native::krr(null_terminated_str_to_const_S(
1877 "enum must be cast to symbol list\0",
1878 ))
1879 }
1880 } else if unsafe { (*sym).value.list.n } <= index {
1881 // Index is out of sym range
1882 unsafe {
1883 native::r0(sym);
1884 native::krr(null_terminated_str_to_const_S("index out of enum range\0"))
1885 }
1886 } else {
1887 let function = format!("{{`{}${} x}}", source, source);
1888 unsafe {
1889 native::r0(sym);
1890 native::k(0, str_to_S!(function.as_str()), native::kj(index), KNULL)
1891 }
1892 }
1893}
1894
1895/// Constructor of q simple list.
1896/// # Example
1897/// See the example of [`new_dictionary`](fn.new_dictionary.html).
1898#[inline]
1899pub fn new_list(qtype: i8, length: J) -> K {
1900 unsafe { native::ktn(qtype as I, length) }
1901}
1902
1903/// Constructor of q string object.
1904/// # Example
1905/// ```no_run
1906/// use kdbplus::api::*;
1907///
1908/// #[no_mangle]
1909/// pub extern "C" fn create_string(_: K) -> K{
1910/// new_string("this is a text.")
1911/// }
1912/// ```
1913/// ```q
1914/// q)text: libc_api_examples 2: (`create_string; 1);
1915/// q)text[]
1916/// "this is a text."
1917/// ```
1918#[inline]
1919pub fn new_string(string: &str) -> K {
1920 unsafe { native::kp(str_to_S!(string)) }
1921}
1922
1923/// Constructor if q string object with a fixed length.
1924/// # Example
1925/// ```no_run
1926/// use kdbplus::api::*;
1927///
1928/// #[no_mangle]
1929/// pub extern "C" fn create_string2(_: K) -> K{
1930/// new_string_n("The meeting was too long and I felt it s...", 24)
1931/// }
1932/// ```
1933/// ```q
1934/// q)speak_inwardly: libc_api_examples 2: (`create_string2; 1);
1935/// q)speak_inwardly[]
1936/// "The meeting was too long"
1937/// ```
1938#[inline]
1939pub fn new_string_n(string: &str, length: J) -> K {
1940 unsafe { native::kpn(str_to_S!(string), length) }
1941}
1942
1943/// Constructor of q dictionary object.
1944/// # Example
1945/// ```no_run
1946/// use kdbplus::api::*;
1947/// use kdbplus::qtype;
1948///
1949/// #[no_mangle]
1950/// pub extern "C" fn create_dictionary() -> K{
1951/// let keys=new_list(qtype::INT_LIST, 2);
1952/// keys.as_mut_slice::<I>()[0..2].copy_from_slice(&[0, 1]);
1953/// let values=new_list(qtype::COMPOUND_LIST, 2);
1954/// let date_list=new_list(qtype::DATE_LIST, 3);
1955/// // 2000.01.01 2000.01.02 2000.01.03
1956/// date_list.as_mut_slice::<I>()[0..3].copy_from_slice(&[0, 1, 2]);
1957/// let string=new_string("I'm afraid I would crash the application...");
1958/// values.as_mut_slice::<K>()[0..2].copy_from_slice(&[date_list, string]);
1959/// new_dictionary(keys, values)
1960/// }
1961/// ```
1962/// ```q
1963/// q)create_dictionary: `libapi_examples 2: (`create_dictionary; 1);
1964/// q)create_dictionary[]
1965/// 0| 2000.01.01 2000.01.02 2000.01.03
1966/// 1| "I'm afraid I would crash the application..."
1967/// ```
1968#[inline]
1969pub fn new_dictionary(keys: K, values: K) -> K {
1970 unsafe { native::xD(keys, values) }
1971}
1972
1973/// Constructor of q general null.
1974/// # Example
1975/// ```no_run
1976/// use kdbplus::qtype;
1977/// use kdbplus::api::*;
1978///
1979/// #[no_mangle]
1980/// pub extern "C" fn nullify(_: K) -> K{
1981/// let nulls=new_list(qtype::COMPOUND_LIST, 3);
1982/// let null_slice=nulls.as_mut_slice::<K>();
1983/// null_slice[0]=new_null();
1984/// null_slice[1]=new_string("null is not a general null");
1985/// null_slice[2]=new_null();
1986/// nulls
1987/// }
1988/// ```
1989/// ```q
1990/// q)void: `libapi_examples 2: (`nullify; 1);
1991/// q)void[]
1992/// ::
1993/// "null is not a general null"
1994/// ::
1995/// ```
1996#[inline]
1997pub fn new_null() -> K {
1998 unsafe {
1999 let null = native::ka(qtype::NULL as I);
2000 (*null).value.byte = 0;
2001 null
2002 }
2003}
2004
2005/// Constructor of q error. The input must be null-terminated.
2006/// # Example
2007/// ```no_run
2008/// use kdbplus::api::*;
2009///
2010/// pub extern "C" fn thai_kick(_: K) -> K{
2011/// new_error("Thai kick unconditionally!!\0")
2012/// }
2013/// ```
2014/// ```q
2015/// q)monstrous: `libapi_examples 2: (`thai_kick; 1);
2016/// q)monstrous[]
2017/// 'Thai kick unconditionally!!
2018/// [0] monstrous[]
2019/// ^
2020/// ```
2021#[inline]
2022pub fn new_error(message: &str) -> K {
2023 unsafe { native::krr(null_terminated_str_to_const_S(message)) }
2024}
2025
2026/// Similar to `new_error` but this function appends a system-error message to string `S` before passing it to internal `krr`.
2027/// The input must be null-terminated.
2028#[inline]
2029pub fn new_error_os(message: &str) -> K {
2030 unsafe { native::orr(null_terminated_str_to_const_S(message)) }
2031}
2032
2033/// Convert an error object into usual `K` object which has the error string in the field `symbol`.
2034/// # Example
2035/// ```no_run
2036/// use kdbplus::*;
2037/// use kdbplus::api::*;
2038///
2039/// extern "C" fn no_panick(func: K, args: K) -> K{
2040/// let result=error_to_string(apply(func, args));
2041/// if let Ok(error) = result.get_error_string(){
2042/// println!("FYI: {}", error);
2043/// // Decrement reference count of the error object which is no longer used.
2044/// decrement_reference_count(result);
2045/// KNULL
2046/// }
2047/// else{
2048/// result
2049/// }
2050/// }
2051/// ```
2052/// ```q
2053/// q)chill: `libapi_examples 2: (`no_panick; 2);
2054/// q)chill[$; ("J"; "42")]
2055/// success!
2056/// 42
2057/// q)chill[+; (1; `a)]
2058/// FYI: type
2059/// ```
2060/// # Note
2061/// If you intend to use the error string only in Rust side and not to return the value, you need
2062/// to decrement the reference count of the error object created by `error_to_string` as shown above.
2063/// If you want to propagate the error to q side after some operation, you can just return it (See the
2064/// example of [`is_error`](fn.is_error.html)).
2065///
2066/// # Warning
2067/// In q, an error is a 0 pointer. This causes a problem of false positive by `error_to_string`, i.e.,
2068/// `KNULL` is also catched as an error object and its type is set `qtype::ERROR`. In such a case you must NOT
2069/// return the catched object because it causes segmentation fault. If you want to check if the catched object
2070/// is an error and then return if it is, you should use [`is_error`](fn.is_error.html). If you want to use the
2071/// underlying error string of the catched object, you should use [`get_error_string`](trait.KUtility.html#tymethod.get_error_string).
2072#[inline]
2073pub fn error_to_string(error: K) -> K {
2074 unsafe { native::ee(error) }
2075}
2076
2077/// Judge if a catched object by [`error_to_string`](fn.error_to_string.html) is a genuine error object of type
2078/// `qtype::ERROR` (This means false positive of the `KNULL` case can be eliminated).
2079/// # Examples
2080/// ```no_run
2081/// use kdbplus::*;
2082/// use kdbplus::api::*;
2083///
2084/// fn love_even(arg: K) -> K{
2085/// if let Ok(int) = arg.get_int(){
2086/// if int % 2 == 0{
2087/// // Silent for even value
2088/// KNULL
2089/// }
2090/// else{
2091/// // Shout against odd value
2092/// new_error("great is the even value!!\0")
2093/// }
2094/// }
2095/// else{
2096/// // Pass through
2097/// increment_reference_count(arg)
2098/// }
2099/// }
2100///
2101/// #[no_mangle]
2102/// pub extern "C" fn propagate(arg: K) -> K{
2103/// let result=error_to_string(love_even(arg));
2104/// if is_error(result){
2105/// // Propagate the error
2106/// result
2107/// }
2108/// else if result.get_type() == qtype::ERROR{
2109/// // KNULL
2110/// println!("this is KNULL");
2111/// decrement_reference_count(result);
2112/// KNULL
2113/// }
2114/// else{
2115/// // Other
2116/// new_symbol("sonomama")
2117/// }
2118/// }
2119/// ```
2120/// ```q
2121/// q)convey: `libapi_examples 2: (`propagate; 1);
2122/// q)convey[7i]
2123/// 'great is the even value!!
2124/// q)convey[12i]
2125/// this is KNULL
2126/// q)convey[5.5]
2127/// `sonomama
2128/// ```
2129/// # Note
2130/// In this example `KNULL` is used as a returned value of the function called by another function to demonstrate
2131/// how `is_error` works. However, `KNULL` should not be used in such a way in order to avoid this kind of complexity.
2132/// To return a general null for inner functions, use [`new_null`](fn.new_null.html) instead.
2133#[inline]
2134pub fn is_error(catched: K) -> bool {
2135 (unsafe { (*catched).qtype } == qtype::ERROR) && !unsafe { (*catched).value.symbol }.is_null()
2136}
2137
2138//%% Symbol %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2139
2140/// Extract the first `n` chars from a character array and enumerate it internally.
2141/// This function must be used to add a character array as a symbol value to a symbol list.
2142/// The returned value is the same character array as the input.
2143/// # Example
2144/// See the example of [`flip`](fn.flip.html).
2145/// # Note
2146/// The reason why this function must be used is to enumerate the character array before handling
2147/// it as a q symbol type value. q/kdb+ is enumerating all symbol values to optimize comparison
2148/// or memory usage. On the other hand [`new_symbol`] does the enumeration internally and
2149/// therefore it does not need this function.
2150#[inline]
2151pub fn enumerate_n(string: S, n: I) -> S {
2152 unsafe { native::sn(string, n) }
2153}
2154
2155/// Enumerate a null-terminated character array internally. This function must be used
2156/// to add a character array as a symbol value to a symbol list. The returned value is
2157/// the same character array as the input.
2158/// # Example
2159/// See the example of [`flip`](fn.flip.html).
2160/// # Note
2161/// The reason why this function must be used is to enumerate the character array before handling
2162/// it as a q symbol type value. q/kdb+ is enumerating all symbol values to optimize comparison
2163/// or memory usage. On the other hand [`new_symbol`] does the enumeration internally and
2164/// therefore it does not need this function.
2165#[inline]
2166pub fn enumerate(string: S) -> S {
2167 unsafe { native::ss(string) }
2168}
2169
2170//%% Table %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2171
2172/// Constructor of q table object from a q dictionary object.
2173/// # Note
2174/// Basically this is a `flip` command of q. Hence the value of the dictionary must have
2175/// lists as its elements.
2176/// ```no_run
2177/// #[macro_use]
2178/// extern crate kdbplus;
2179/// use kdbplus::api::*;
2180/// use kdbplus::qtype;
2181///
2182/// #[no_mangle]
2183/// pub extern "C" fn create_table2(_: K) -> K{
2184/// // Build keys
2185/// let keys=new_list(qtype::SYMBOL_LIST, 2);
2186/// let keys_slice=keys.as_mut_slice::<S>();
2187/// keys_slice[0]=enumerate(str_to_S!("time"));
2188/// keys_slice[1]=enumerate_n(str_to_S!("temperature_and_humidity"), 11);
2189///
2190/// // Build values
2191/// let values=new_list(qtype::COMPOUND_LIST, 2);
2192/// let time=new_list(qtype::TIMESTAMP_LIST, 3);
2193/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
2194/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
2195/// let temperature=new_list(qtype::FLOAT_LIST, 3);
2196/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
2197/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
2198///
2199/// flip(new_dictionary(keys, values))
2200/// }
2201/// ```
2202/// ```q
2203/// q)climate_change: libc_api_examples 2: (`create_table2; 1);
2204/// q)climate_change[]
2205/// time temperature
2206/// -----------------------------------------
2207/// 2003.10.10D02:24:19.167018272 22.1
2208/// 2006.05.24D06:16:49.419710368 24.7
2209/// 2008.08.12D23:12:24.018691392 30.5
2210/// ```
2211#[inline]
2212pub fn flip(dictionary: K) -> K {
2213 match unsafe { (*dictionary).qtype } {
2214 qtype::DICTIONARY => unsafe { native::xT(dictionary) },
2215 _ => unsafe { native::krr(null_terminated_str_to_const_S("not a dictionary\0")) },
2216 }
2217}
2218
2219/// Constructor of simple q table object from a q keyed table object.
2220/// # Example
2221/// ```no_run
2222/// #[macro_use]
2223/// extern crate kdbplus;
2224/// use kdbplus::api::*;
2225/// use kdbplus::qtype;
2226///
2227/// #[no_mangle]
2228/// pub extern "C" fn create_table2(_: K) -> K{
2229/// // Build keys
2230/// let keys=new_list(qtype::SYMBOL_LIST, 2);
2231/// let keys_slice=keys.as_mut_slice::<S>();
2232/// keys_slice[0]=enumerate(str_to_S!("time"));
2233/// keys_slice[1]=enumerate_n(str_to_S!("temperature_and_humidity"), 11);
2234///
2235/// // Build values
2236/// let values=new_list(qtype::COMPOUND_LIST, 2);
2237/// let time=new_list(qtype::TIMESTAMP_LIST, 3);
2238/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
2239/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
2240/// let temperature=new_list(qtype::FLOAT_LIST, 3);
2241/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
2242/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
2243///
2244/// flip(new_dictionary(keys, values))
2245/// }
2246///
2247/// #[no_mangle]
2248/// pub extern "C" fn create_keyed_table(dummy: K) -> K{
2249/// enkey(create_table2(dummy), 1)
2250/// }
2251///
2252/// #[no_mangle]
2253/// pub extern "C" fn keyed_to_simple_table(dummy: K) -> K{
2254/// unkey(create_keyed_table(dummy))
2255/// }
2256/// ```
2257/// ```q
2258/// q)unkey: libc_api_examples 2: (`keyed_to_simple_table; 1);
2259/// q)unkey[]
2260/// time temperature
2261/// -----------------------------------------
2262/// 2003.10.10D02:24:19.167018272 22.1
2263/// 2006.05.24D06:16:49.419710368 24.7
2264/// 2008.08.12D23:12:24.018691392 30.5
2265/// ```
2266#[inline]
2267pub fn unkey(keyed_table: K) -> K {
2268 match unsafe { (*keyed_table).qtype } {
2269 qtype::DICTIONARY => unsafe { native::ktd(keyed_table) },
2270 _ => unsafe { native::krr(null_terminated_str_to_const_S("not a keyed table\0")) },
2271 }
2272}
2273
2274/// Constructor of q keyed table object.
2275/// # Parameters
2276/// - `table`: q table object to be enkeyed.
2277/// - `n`: The number of key columns from the left.
2278/// # Example
2279/// ```no_run
2280/// #[macro_use]
2281/// extern crate kdbplus;
2282/// use kdbplus::api::*;
2283/// use kdbplus::qtype;
2284///
2285/// #[no_mangle]
2286/// pub extern "C" fn create_table2(_: K) -> K{
2287/// // Build keys
2288/// let keys=new_list(qtype::SYMBOL_LIST, 2);
2289/// let keys_slice=keys.as_mut_slice::<S>();
2290/// keys_slice[0]=enumerate(str_to_S!("time"));
2291/// keys_slice[1]=enumerate_n(str_to_S!("temperature_and_humidity"), 11);
2292///
2293/// // Build values
2294/// let values=new_list(qtype::COMPOUND_LIST, 2);
2295/// let time=new_list(qtype::TIMESTAMP_LIST, 3);
2296/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
2297/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
2298/// let temperature=new_list(qtype::FLOAT_LIST, 3);
2299/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
2300/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
2301///
2302/// flip(new_dictionary(keys, values))
2303/// }
2304///
2305/// #[no_mangle]
2306/// pub extern "C" fn create_keyed_table(dummy: K) -> K{
2307/// enkey(create_table2(dummy), 1)
2308/// }
2309/// ```
2310/// ```q
2311/// q)locker: libc_api_examples 2: (`create_keyed_table; 1);
2312/// q)locker[]
2313/// time | temperature
2314/// -----------------------------| -----------
2315/// 2003.10.10D02:24:19.167018272| 22.1
2316/// 2006.05.24D06:16:49.419710368| 24.7
2317/// 2008.08.12D23:12:24.018691392| 30.5
2318/// ```
2319#[inline]
2320pub fn enkey(table: K, n: J) -> K {
2321 match unsafe { (*table).qtype } {
2322 qtype::TABLE => unsafe { native::knt(n, table) },
2323 _ => unsafe { native::krr(null_terminated_str_to_const_S("not a table\0")) },
2324 }
2325}
2326
2327//%% Reference Count %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2328
2329/// Decrement reference count of the q object. The decrement must be done when `k` function gets an error
2330/// object whose type is `qtype::ERROR` and when you created an object but do not intend to return it to
2331/// q side. See details on [the reference page](https://code.kx.com/q/interfaces/c-client-for-q/#managing-memory-and-reference-counting).
2332/// # Example
2333/// ```no_run
2334/// use kdbplus::api::*;
2335///
2336/// #[no_mangle]
2337/// pub extern "C" fn agriculture(_: K)->K{
2338/// // Produce an apple.
2339/// let fruit=new_symbol("apple");
2340/// // Sow the apple seed.
2341/// decrement_reference_count(fruit);
2342/// // Return null.
2343/// KNULL
2344/// }
2345/// ```
2346/// ```q
2347/// q)do_something: `libapi_examples 2: (`agriculture; 1);
2348/// q)do_something[]
2349/// q)
2350/// ```
2351#[inline]
2352pub fn decrement_reference_count(qobject: K) -> V {
2353 unsafe { native::r0(qobject) }
2354}
2355
2356/// Increment reference count of the q object. Increment must be done when you passed arguments
2357/// to Rust function and intends to return it to q side or when you pass some `K` objects to `k`
2358/// function and intend to use the argument after the call.
2359/// See details on [the reference page](https://code.kx.com/q/interfaces/c-client-for-q/#managing-memory-and-reference-counting).
2360/// # Example
2361/// ```no_run
2362/// #[macro_use]
2363/// extern crate kdbplus;
2364/// use kdbplus::api::*;
2365///
2366/// fn eat(apple: K){
2367/// println!("おいしい!");
2368/// }
2369///
2370/// #[no_mangle]
2371/// pub extern "C" fn satisfy_5000_men(apple: K) -> K{
2372/// for _ in 0..10{
2373/// eat(apple);
2374/// }
2375/// unsafe{native::k(0, str_to_S!("eat"), increment_reference_count(apple), KNULL);}
2376/// increment_reference_count(apple)
2377/// }
2378/// ```
2379/// ```q
2380/// q)eat:{[apple] show "Collect the clutter of apples!";}
2381/// q)bread_is_a_sermon: libc_api_examples 2: (`satisfy_5000_men; 1);
2382/// q)bread_is_a_sermon[`green_apple]
2383/// おいしい!
2384/// おいしい!
2385/// おいしい!
2386/// おいしい!
2387/// おいしい!
2388/// おいしい!
2389/// おいしい!
2390/// おいしい!
2391/// おいしい!
2392/// おいしい!
2393/// "Collect the clutter of apples!"
2394/// ```
2395#[inline]
2396pub fn increment_reference_count(qobject: K) -> K {
2397 unsafe { native::r1(qobject) }
2398}
2399
2400//%% Callback %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2401
2402/// Remove callback from the associated kdb+ socket and call `kclose`.
2403/// Return null if the socket is invalid or not the one which had been registered by `sd1`.
2404/// # Note
2405/// A function which calls this function must be executed at the exit of the process.
2406#[inline]
2407pub fn destroy_socket(socket: I) {
2408 unsafe {
2409 native::sd0(socket);
2410 }
2411}
2412
2413/// Remove callback from the associated kdb+ socket and call `kclose` if the given condition is satisfied.
2414/// Return null if the socket is invalid or not the one which had been registered by `sd1`.
2415/// # Note
2416/// A function which calls this function must be executed at the exit of the process.
2417#[inline]
2418pub fn destroy_socket_if(socket: I, condition: bool) {
2419 unsafe {
2420 native::sd0x(socket, condition as I);
2421 }
2422}
2423
2424/// Register callback to the associated kdb+ socket.
2425/// ```no_run
2426/// #[macro_use]
2427/// extern crate kdbplus;
2428/// use kdbplus::api::*;
2429/// use kdbplus::qtype;
2430///
2431/// static mut PIPE:[I; 2]=[-1, -1];
2432///
2433/// // Callback for some message queue.
2434/// extern "C" fn callback(socket: I)->K{
2435/// let mut buffer: [K; 1]=[0 as K];
2436/// unsafe{libc::read(socket, buffer.as_mut_ptr() as *mut V, 8)};
2437/// // Call `shout` function on q side with the received data.
2438/// let result=error_to_string(unsafe{native::k(0, str_to_S!("shout"), buffer[0], KNULL)});
2439/// if result.get_type() == qtype::ERROR{
2440/// eprintln!("Execution error: {}", result.get_symbol().unwrap());
2441/// decrement_reference_count(result);
2442/// };
2443/// KNULL
2444/// }
2445///
2446/// #[no_mangle]
2447/// pub extern "C" fn plumber(_: K) -> K{
2448/// if 0 != unsafe{libc::pipe(PIPE.as_mut_ptr())}{
2449/// return new_error("Failed to create pipe\0");
2450/// }
2451/// if KNULL == register_callback(unsafe{PIPE[0]}, callback){
2452/// return new_error("Failed to register callback\0");
2453/// }
2454/// // Lock symbol in a worker thread.
2455/// pin_symbol();
2456/// let handle=std::thread::spawn(move ||{
2457/// let mut precious=new_list(qtype::SYMBOL_LIST, 3);
2458/// let precious_array=precious.as_mut_slice::<S>();
2459/// precious_array[0]=enumerate(null_terminated_str_to_S("belief\0"));
2460/// precious_array[1]=enumerate(null_terminated_str_to_S("love\0"));
2461/// precious_array[2]=enumerate(null_terminated_str_to_S("hope\0"));
2462/// unsafe{libc::write(PIPE[1], std::mem::transmute::<*mut K, *mut V>(&mut precious), 8)};
2463/// });
2464/// handle.join().unwrap();
2465/// unpin_symbol();
2466/// KNULL
2467/// }
2468/// ```
2469/// ```q
2470/// q)shout:{[precious] -1 "What are the three largest elements?: ", .Q.s1 precious;};
2471/// q)fall_into_pipe: `libc_api_example 2: (`plumber; 1);
2472/// q)fall_into_pipe[]
2473/// What are the three largest elements?: `belief`love`hope
2474/// ```
2475#[inline]
2476pub fn register_callback(socket: I, function: extern "C" fn(I) -> K) -> K {
2477 unsafe { native::sd1(socket, function) }
2478}
2479
2480//%% Miscellaneous %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2481
2482/// Apply a function to q list object `.[func; args]`.
2483/// # Example
2484/// See the example of [`error_to_string`](fn.error_to_string.html).
2485#[inline]
2486pub fn apply(func: K, args: K) -> K {
2487 unsafe { native::dot(func, args) }
2488}
2489
2490/// Enable the remote threads to refer to the sym list in the main thread so that enumeration
2491/// of remotely created symbol values reain valid in the main thread after joining the
2492/// remote threads. This function must be used before starting any other threads if the
2493/// threads create symbol values. The previously set value is returned.
2494/// # Example
2495/// See the example of [`register_callback`](fn.register_callback.html).
2496#[inline]
2497pub fn pin_symbol() -> I {
2498 unsafe { native::setm(1) }
2499}
2500
2501/// Unlock the symbol list in the main thread. This function should be called after joining
2502/// threads.
2503/// # Example
2504/// See the example of [`register_callback`](fn.register_callback.html).
2505#[inline]
2506pub fn unpin_symbol() -> I {
2507 unsafe { native::setm(0) }
2508}
2509
2510/// Drop Rust object inside q. Passed as the first element of a foreign object.
2511/// # Parameters
2512/// - `obj`: List of (function to free the object; foreign object).
2513/// # Example
2514/// See the example of [`load_as_q_function`](fn.load_as_q_function.html).
2515pub fn drop_q_object(obj: K) -> K {
2516 let obj_slice = obj.as_mut_slice::<K>();
2517 // Take ownership of `K` object from a raw pointer and drop at the end of this scope.
2518 unsafe {
2519 let _ = Box::from_raw(obj_slice[1]);
2520 };
2521 // Fill the list with null.
2522 obj_slice.copy_from_slice(&[KNULL, KNULL]);
2523 obj
2524}
2525
2526/// Load C function as a q function (`K` object).
2527/// # Parameters
2528/// - `func`: A function takes a C function that would take `n` `K` objects as arguments and returns a `K` object.
2529/// - `n`: The number of arguments for the function.
2530/// # Example
2531/// ```no_run
2532/// #[macro_use]
2533/// extern crate kdbplus;
2534/// use kdbplus::api::*;
2535/// use kdbplus::qtype;
2536///
2537/// #[derive(Clone, Debug)]
2538/// struct Planet{
2539/// name: String,
2540/// population: i64,
2541/// water: bool
2542/// }
2543///
2544/// impl Planet{
2545/// /// Constructor of `Planet`.
2546/// fn new(name: &str, population: i64, water: bool) -> Self{
2547/// Planet{
2548/// name: name.to_string(),
2549/// population: population,
2550/// water: water
2551/// }
2552/// }
2553///
2554/// /// Description of the planet.
2555/// fn description(&self)->String{
2556/// let mut desc=format!("The planet {} is a beautiful planet where {} people reside.", self.name, self.population);
2557/// if self.water{
2558/// desc+=" Furthermore water is flowing on the surface of it.";
2559/// }
2560/// desc
2561/// }
2562/// }
2563///
2564/// /// Example of `set_type`.
2565/// #[no_mangle]
2566/// pub extern "C" fn eden(_: K) -> K{
2567/// let earth=Planet::new("earth", 7500_000_000, true);
2568/// let mut foreign=new_list(qtype::COMPOUND_LIST, 2);
2569/// let foreign_slice=foreign.as_mut_slice::<K>();
2570/// foreign_slice[0]=drop_q_object as K;
2571/// foreign_slice[1]=Box::into_raw(Box::new(earth)) as K;
2572/// // Set as foreign object.
2573/// foreign.set_type(qtype::FOREIGN);
2574/// foreign
2575/// }
2576///
2577/// extern "C" fn invade(planet: K, action: K) -> K{
2578/// let obj=planet.as_mut_slice::<K>()[1] as *const Planet;
2579/// println!("{:?}", unsafe{obj.as_ref()}.unwrap());
2580/// let mut desc=unsafe{obj.as_ref()}.unwrap().description();
2581/// if action.get_bool().unwrap(){
2582/// desc+=" You shall not curse what God blessed.";
2583/// }
2584/// else{
2585/// desc+=" I perceived I could find favor of God by blessing them.";
2586/// }
2587/// new_string(&desc)
2588/// }
2589///
2590/// /// Example of `load_as_q_function`.
2591/// #[no_mangle]
2592/// pub extern "C" fn probe(planet: K)->K{
2593/// // Return monadic function
2594/// unsafe{native::k(0, str_to_S!("{[func; planet] func[planet]}"), load_as_q_function(invade as *const V, 2), planet, KNULL)}
2595/// }
2596/// ```
2597/// ```q
2598/// q)eden: libc_api_example 2: (`eden; 1);
2599/// q)earth: eden[]
2600/// q)type earth
2601/// 112h
2602/// q)probe: libc_api_example 2: (`probe; 1);
2603/// q)invade: probe[earth];
2604/// q)\c 25 200
2605/// q)invade 1b
2606/// "The planet earth is a beautiful planet where 7500000000 people reside. Furthermore water is flowing on the surface of it. You shall not curse what God blessed."
2607/// ```
2608#[inline]
2609pub fn load_as_q_function(func: *const V, n: J) -> K {
2610 unsafe { native::dl(func, n) }
2611}
2612
2613/// Convert ymd to the number of days from `2000.01.01`.
2614/// # Example
2615/// ```no_run
2616/// use kdbplus::api::*;
2617///
2618/// let days=ymd_to_days(2020, 4, 1);
2619/// assert_eq!(days, 7396);
2620/// ```
2621#[inline]
2622pub fn ymd_to_days(year: I, month: I, date: I) -> I {
2623 unsafe { native::ymd(year, month, date) }
2624}
2625
2626/// Convert the number of days from `2000.01.01` to a number expressed as `yyyymmdd`.
2627/// # Example
2628/// ```no_run
2629/// use kdbplus::api::*;
2630///
2631/// let number=days_to_ymd(7396);
2632/// assert_eq!(number, 20200401);
2633/// ```
2634#[inline]
2635pub fn days_to_ymd(days: I) -> I {
2636 unsafe { native::dj(days) }
2637}
2638
2639/// Convert a simple list to a compound list. Expected usage is to concatinate a simple list
2640/// with a different type of list.
2641/// # Example
2642/// ```no_run
2643/// use kdbplus::*;
2644/// use kdbplus::api::*;
2645///
2646/// #[no_mangle]
2647/// pub extern "C" fn drift(_: K)->K{
2648/// let simple=new_list(qtype::INT_LIST, 2);
2649/// simple.as_mut_slice::<I>().copy_from_slice(&[12, 34]);
2650/// let extra=new_list(qtype::COMPOUND_LIST, 2);
2651/// extra.as_mut_slice::<K>().copy_from_slice(&[new_symbol("vague"), new_int(-3000)]);
2652/// // Convert an integer list into a compound list
2653/// let mut compound = simple_to_compound(simple, "");
2654/// compound.append(extra).unwrap()
2655/// }
2656///
2657/// #[no_mangle]
2658/// pub extern "C" fn drift2(_: K)->K{
2659/// let simple=new_list(qtype::ENUM_LIST, 2);
2660/// simple.as_mut_slice::<J>().copy_from_slice(&[0_i64, 1]);
2661/// // Convert an enum indices into a compound list while creating enum values from the indices which are tied with
2662/// // an existing enum variable named "enum", i.e., Enum indices [0, 1] in the code are cast into `(enum[0]; enum[1])`.
2663/// let mut compound = simple_to_compound(simple, "enum");
2664/// // Add `enum2[2]`.
2665/// compound.push(new_enum("enum2", 2)).unwrap();
2666/// compound.push(new_month(3)).unwrap();
2667/// compound
2668/// }
2669/// ```
2670/// ```q
2671/// q)drift: LIBPATH_ (`drift; 1);
2672/// q)drift2: LIBPATH_ (`drift2; 1);
2673/// q)drift[]
2674/// 12i
2675/// 34i
2676/// `vague
2677/// -3000i
2678/// q)enum: `mashroom`broccoli`cucumber
2679/// q)enum2: `mackerel`swordfish`tuna
2680/// q)drift2[]
2681/// `enum$`mashroom
2682/// `enum$`broccoli
2683/// `enum2$`tuna
2684/// 2000.04m
2685/// ```
2686/// # Note
2687/// - To convert a list provided externally (i.e., passed from a q process), apply
2688/// [`increment_reference_count`](fn.increment_reference_count.html) before converting the list.
2689/// - Enum elements from different enum sources must be contained in a compound list. Therefore
2690/// this function intentionally restricts the number of enum sources to one so that user switches
2691/// a simple list to a compound list when the second enum sources are provided.
2692pub fn simple_to_compound(simple: K, enum_source: &str) -> K {
2693 let size = simple.len() as usize;
2694 let compound = new_list(qtype::COMPOUND_LIST, size as J);
2695 let compound_slice = compound.as_mut_slice::<K>();
2696 match simple.get_type() {
2697 qtype::BOOL_LIST => {
2698 let simple_slice = simple.as_mut_slice::<G>();
2699 for i in 0..size {
2700 compound_slice[i] = new_bool(simple_slice[i] as I);
2701 }
2702 }
2703 qtype::GUID_LIST => {
2704 let simple_slice = simple.as_mut_slice::<U>();
2705 for i in 0..size {
2706 compound_slice[i] = new_guid(simple_slice[i].guid);
2707 }
2708 }
2709 qtype::BYTE_LIST => {
2710 let simple_slice = simple.as_mut_slice::<G>();
2711 for i in 0..size {
2712 compound_slice[i] = new_byte(simple_slice[i] as I);
2713 }
2714 }
2715 qtype::SHORT_LIST => {
2716 let simple_slice = simple.as_mut_slice::<H>();
2717 for i in 0..size {
2718 compound_slice[i] = new_short(simple_slice[i] as I);
2719 }
2720 }
2721 qtype::INT_LIST => {
2722 let simple_slice = simple.as_mut_slice::<I>();
2723 for i in 0..size {
2724 compound_slice[i] = new_int(simple_slice[i]);
2725 }
2726 }
2727 qtype::LONG_LIST => {
2728 let simple_slice = simple.as_mut_slice::<J>();
2729 for i in 0..size {
2730 compound_slice[i] = new_long(simple_slice[i]);
2731 }
2732 }
2733 qtype::REAL_LIST => {
2734 let simple_slice = simple.as_mut_slice::<E>();
2735 for i in 0..size {
2736 compound_slice[i] = new_real(simple_slice[i] as F);
2737 }
2738 }
2739 qtype::FLOAT_LIST => {
2740 let simple_slice = simple.as_mut_slice::<F>();
2741 for i in 0..size {
2742 compound_slice[i] = new_float(simple_slice[i]);
2743 }
2744 }
2745 qtype::STRING => {
2746 let simple_slice = simple.as_mut_slice::<G>();
2747 for i in 0..size {
2748 compound_slice[i] = new_char(simple_slice[i] as char);
2749 }
2750 }
2751 qtype::SYMBOL_LIST => {
2752 let simple_slice = simple.as_mut_slice::<S>();
2753 for i in 0..size {
2754 compound_slice[i] = new_symbol(S_to_str(simple_slice[i]));
2755 }
2756 }
2757 qtype::TIMESTAMP_LIST => {
2758 let simple_slice = simple.as_mut_slice::<J>();
2759 for i in 0..size {
2760 compound_slice[i] = new_timestamp(simple_slice[i]);
2761 }
2762 }
2763 qtype::DATE_LIST => {
2764 let simple_slice = simple.as_mut_slice::<I>();
2765 for i in 0..size {
2766 compound_slice[i] = new_date(simple_slice[i]);
2767 }
2768 }
2769 qtype::TIME_LIST => {
2770 let simple_slice = simple.as_mut_slice::<I>();
2771 for i in 0..size {
2772 compound_slice[i] = new_time(simple_slice[i]);
2773 }
2774 }
2775 qtype::ENUM_LIST => {
2776 let simple_slice = simple.as_mut_slice::<J>();
2777 for i in 0..size {
2778 compound_slice[i] = new_enum(enum_source, simple_slice[i]);
2779 }
2780 }
2781 _ => {
2782 decrement_reference_count(compound);
2783 return new_error("not a simple list\0");
2784 }
2785 }
2786 // Free simple list
2787 decrement_reference_count(simple);
2788 compound
2789}