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) -> i8;
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 #[allow(clippy::unnecessary_cast)]
1198 unsafe {
1199 (**self).attribute as i8
1200 }
1201 }
1202
1203 #[inline]
1204 fn get_refcount(&self) -> i32 {
1205 unsafe { (**self).refcount }
1206 }
1207
1208 #[inline]
1209 fn append(&mut self, list: K) -> Result<K, &'static str> {
1210 if unsafe { (**self).qtype } >= 0 && unsafe { (**self).qtype } == unsafe { (*list).qtype } {
1211 let result = Ok(unsafe { native::jv(self, list) });
1212 // Free appended list for internally created object.
1213 unsafe { native::r0(list) };
1214 result
1215 } else {
1216 Err("not a list or types do not match\0")
1217 }
1218 }
1219
1220 #[inline]
1221 fn push(&mut self, atom: K) -> Result<K, &'static str> {
1222 match unsafe { (**self).qtype } {
1223 qtype::COMPOUND_LIST => Ok(unsafe { native::jk(self, atom) }),
1224 _ => Err("not a list or types do not match\0"),
1225 }
1226 }
1227
1228 #[inline]
1229 fn push_raw<T>(&mut self, mut atom: T) -> Result<K, &'static str> {
1230 match unsafe { (**self).qtype } {
1231 _t @ qtype::BOOL_LIST..=qtype::ENUM_LIST => {
1232 Ok(unsafe { native::ja(self, std::mem::transmute::<*mut T, *mut V>(&mut atom)) })
1233 }
1234 _ => Err("not a simple list or types do not match\0"),
1235 }
1236 }
1237
1238 #[inline]
1239 fn push_symbol(&mut self, symbol: &str) -> Result<K, &'static str> {
1240 match unsafe { (**self).qtype } {
1241 qtype::SYMBOL_LIST => Ok(unsafe { native::js(self, native::ss(str_to_S!(symbol))) }),
1242 _ => Err("not a symbol list\0"),
1243 }
1244 }
1245
1246 #[inline]
1247 fn push_symbol_n(&mut self, symbol: &str, n: I) -> Result<K, &'static str> {
1248 match unsafe { (**self).qtype } {
1249 qtype::SYMBOL_LIST => Ok(unsafe { native::js(self, native::sn(str_to_S!(symbol), n)) }),
1250 _ => Err("not a symbol list or types do not match\0"),
1251 }
1252 }
1253
1254 #[inline]
1255 fn len(&self) -> i64 {
1256 match unsafe { (**self).qtype } {
1257 _t @ qtype::ENUM_ATOM..=qtype::BOOL_ATOM => {
1258 // Atom
1259 1
1260 }
1261 _t @ qtype::COMPOUND_LIST..=qtype::ENUM_LIST => {
1262 // List
1263 unsafe { (**self).value.list }.n
1264 }
1265 qtype::TABLE => {
1266 // Table
1267 // Access underlying table (dictionary structure) and retrieve values of the dictionary.
1268 // The values (columns) is assured to be a list of lists as it is a table. so cast it to list of `K`.
1269 // Size of the table is a length of the first column.
1270 unsafe {
1271 (*((**self).value.table).as_mut_slice::<K>()[1].as_mut_slice::<K>()[0])
1272 .value
1273 .list
1274 }
1275 .n
1276 }
1277 qtype::DICTIONARY | qtype::SORTED_DICTIONARY => {
1278 // Dictionary
1279 // Access to keys of the dictionary and retrieve its length.
1280 unsafe { (*(*self).as_mut_slice::<K>()[0]).value.list }.n
1281 }
1282 _ => {
1283 // General null, function, foreign
1284 1
1285 }
1286 }
1287 }
1288
1289 #[inline]
1290 fn get_type(&self) -> i8 {
1291 unsafe { (**self).qtype }
1292 }
1293
1294 #[inline]
1295 fn set_type(&mut self, qtype: i8) {
1296 unsafe { (**self).qtype = qtype };
1297 }
1298
1299 #[inline]
1300 fn set_attribute(&mut self, attribute: i8) -> Result<(), &'static str> {
1301 match unsafe { (**self).qtype } {
1302 _t @ qtype::BOOL_LIST..=qtype::TIME_LIST => {
1303 unsafe { (**self).attribute = attribute as C };
1304 Ok(())
1305 }
1306 _ => Err("not a simple list\0"),
1307 }
1308 }
1309
1310 #[inline]
1311 fn q_ipc_encode(&self, mode: I) -> Result<K, &'static str> {
1312 let result = error_to_string(unsafe { native::b9(mode, *self) });
1313 match unsafe { (*result).qtype } {
1314 qtype::ERROR => {
1315 decrement_reference_count(result);
1316 Err("failed to encode\0")
1317 }
1318 _ => Ok(result),
1319 }
1320 }
1321
1322 #[inline]
1323 fn q_ipc_decode(&self) -> Result<K, &'static str> {
1324 match unsafe { (**self).qtype } {
1325 qtype::BYTE_LIST => {
1326 let result = error_to_string(unsafe { native::d9(*self) });
1327 match unsafe { (*result).qtype } {
1328 qtype::ERROR => {
1329 decrement_reference_count(result);
1330 Err("failed to decode\0")
1331 }
1332 _ => Ok(result),
1333 }
1334 }
1335 _ => Err("not bytes\0"),
1336 }
1337 }
1338}
1339
1340impl k0 {
1341 /// Derefer `k0` as a mutable slice. For supported types, see [`as_mut_slice`](trait.KUtility.html#tymethod.as_mut_slice).
1342 /// # Note
1343 /// Used if `K` needs to be sent to another thread. `K` cannot implement `Send` and therefore
1344 /// its inner struct must be sent instead.
1345 /// # Example
1346 /// See the example of [`setm`](native/fn.setm.html).
1347 #[inline]
1348 pub fn as_mut_slice<'a, T>(&mut self) -> &'a mut [T] {
1349 unsafe {
1350 std::slice::from_raw_parts_mut(
1351 self.value.list.G0.as_mut_ptr() as *mut T,
1352 self.value.list.n as usize,
1353 )
1354 }
1355 }
1356}
1357
1358//++++++++++++++++++++++++++++++++++++++++++++++++++//
1359// >> Utility
1360//++++++++++++++++++++++++++++++++++++++++++++++++++//
1361
1362//%% Utility %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1363
1364/// Convert `S` to `&str`. This function is intended to convert symbol type (null-terminated char-array) to `str`.
1365/// # Extern
1366/// ```no_run
1367/// use kdbplus::*;
1368/// use kdbplus::api::*;
1369///
1370/// #[no_mangle]
1371/// pub extern "C" fn print_symbol(symbol: K) -> K{
1372/// unsafe{
1373/// if (*symbol).qtype == qtype::SYMBOL_ATOM{
1374/// println!("symbol: `{}", S_to_str((*symbol).value.symbol));
1375/// }
1376/// // return null
1377/// KNULL
1378/// }
1379/// }
1380/// ```
1381/// ```q
1382/// q)print_symbol:`libapi_examples 2: (`print_symbol; 1)
1383/// q)a:`kx
1384/// q)print_symbol a
1385/// symbol: `kx
1386/// ```
1387#[inline]
1388pub fn S_to_str<'a>(cstring: S) -> &'a str {
1389 unsafe { CStr::from_ptr(cstring).to_str().unwrap() }
1390}
1391
1392/// Convert null-terminated `&str` to `S`.
1393/// # Example
1394/// ```no_run
1395/// use kdbplus::api::*;
1396///
1397/// #[no_mangle]
1398/// pub extern "C" fn pingpong2(_: K) -> K{
1399/// unsafe{native::k(0, null_terminated_str_to_S("ping\0"), new_int(77), KNULL)}
1400/// }
1401/// ```
1402/// ```q
1403/// q)ping:{[int] `$string[int], "_pong!!"};
1404/// q)pingpong: `libapi_examples 2: (`pingpong2; 1);
1405/// q)pingpong[]
1406/// `77_pong!!
1407/// ```
1408#[inline]
1409pub fn null_terminated_str_to_S(string: &str) -> S {
1410 unsafe { CStr::from_bytes_with_nul_unchecked(string.as_bytes()).as_ptr() as S }
1411}
1412
1413/// Convert null terminated `&str` into `const_S`. Expected usage is to build
1414/// a q error object with `krr`.
1415/// # Example
1416/// ```no_run
1417/// use kdbplus::api::*;
1418/// use kdbplus::api::native::*;
1419/// use kdbplus::qtype;
1420///
1421/// pub extern "C" fn must_be_int2(obj: K) -> K{
1422/// unsafe{
1423/// if (*obj).qtype != qtype::INT_ATOM{
1424/// krr(null_terminated_str_to_const_S("not an int\0"))
1425/// }
1426/// else{
1427/// KNULL
1428/// }
1429/// }
1430/// }
1431/// ```
1432/// ```q
1433/// q)check:`libapi_examples 2: (`must_be_int; 1)
1434/// q)a:100
1435/// q)check a
1436/// 'not an int
1437/// [0] check a
1438/// ^
1439/// q)a:42i
1440/// q)check a
1441/// ```
1442pub fn null_terminated_str_to_const_S(string: &str) -> const_S {
1443 string.as_bytes().as_ptr() as const_S
1444}
1445
1446//++++++++++++++++++++++++++++++++++++++++++++++++++//
1447// >> Re-export
1448//++++++++++++++++++++++++++++++++++++++++++++++++++//
1449
1450//%% Constructor %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1451
1452/// Constructor of q bool object. Relabeling of `kb`.
1453/// # Example
1454/// ```no_run
1455/// use kdbplus::api::*;
1456///
1457/// #[no_mangle]
1458/// pub extern "C" fn create_bool(_: K) -> K{
1459/// new_bool(0)
1460/// }
1461/// ```
1462/// ```q
1463/// q)no: `libapi_examples 2: (`create_bool; 1);
1464/// q)no[]
1465/// 0b
1466/// ```
1467#[inline]
1468pub fn new_bool(boolean: I) -> K {
1469 unsafe { native::kb(boolean) }
1470}
1471
1472/// Constructor of q GUID object. Relabeling of `ku`.
1473/// # Example
1474/// ```no_run
1475/// use kdbplus::api::*;
1476///
1477/// #[no_mangle]
1478/// pub extern "C" fn create_guid(_: K) -> K{
1479/// new_guid([0x1e_u8, 0x11, 0x17, 0x0c, 0x42, 0x24, 0x25, 0x2c, 0x1c, 0x14, 0x1e, 0x22, 0x4d, 0x3d, 0x46, 0x24])
1480/// }
1481/// ```
1482/// ```q
1483/// q)create_guid: `libapi_examples 2: (`create_guid; 1);
1484/// q)create_guid[]
1485/// 1e11170c-4224-252c-1c14-1e224d3d4624
1486/// ```
1487#[inline]
1488pub fn new_guid(guid: [G; 16]) -> K {
1489 unsafe { native::ku(U::new(guid)) }
1490}
1491
1492/// Constructor of q byte object. Relabeling of `kg`.
1493/// # Example
1494/// ```no_run
1495/// use kdbplus::api::*;
1496///
1497/// #[no_mangle]
1498/// pub extern "C" fn create_byte(_: K) -> K{
1499/// new_byte(0x3c)
1500/// }
1501/// ```
1502/// ```q
1503/// q)create_byte: `libapi_examples 2: (`create_byte; 1);
1504/// q)create_byte[]
1505/// 0x3c
1506/// ```
1507#[inline]
1508pub fn new_byte(byte: I) -> K {
1509 unsafe { native::kg(byte) }
1510}
1511
1512/// Constructor of q short object. Relabeling of `kh`.
1513/// # Example
1514/// ```no_run
1515/// use kdbplus::api::*;
1516///
1517/// #[no_mangle]
1518/// pub extern "C" fn create_short(_: K) -> K{
1519/// new_short(-144)
1520/// }
1521/// ```
1522/// ```q
1523/// q)shortage: `libapi_examples 2: (`create_short; 1);
1524/// q)shortage[]
1525/// -144h
1526/// ```
1527#[inline]
1528pub fn new_short(short: I) -> K {
1529 unsafe { native::kh(short) }
1530}
1531
1532/// Constructor of q int object. Relabeling of `ki`.
1533/// # Example
1534/// ```no_run
1535/// use kdbplus::api::*;
1536///
1537/// #[no_mangle]
1538/// pub extern "C" fn create_int(_: K) -> K{
1539/// new_int(86400000)
1540/// }
1541/// ```
1542/// ```q
1543/// q)trvial: `libapi_examples 2: (`create_int; 1);
1544/// q)trivial[]
1545/// 86400000i
1546/// ```
1547#[inline]
1548pub fn new_int(int: I) -> K {
1549 unsafe { native::ki(int) }
1550}
1551
1552/// Constructor of q long object. Relabeling of `kj`.
1553/// # Example
1554/// ```no_run
1555/// use kdbplus::api::*;
1556///
1557/// #[no_mangle]
1558/// pub extern "C" fn create_long(_: K) -> K{
1559/// new_long(-668541276001729000)
1560/// }
1561/// ```
1562/// ```q
1563/// q)lengthy: `libapi_examples 2: (`create_long; 1);
1564/// q)lengthy[]
1565/// -668541276001729000
1566/// ```
1567#[inline]
1568pub fn new_long(long: J) -> K {
1569 unsafe { native::kj(long) }
1570}
1571
1572/// Constructor of q real object. Relabeling of `ke`.
1573/// # Example
1574/// ```no_run
1575/// use kdbplus::api::*;
1576///
1577/// #[no_mangle]
1578/// pub extern "C" fn create_real(_: K) -> K{
1579/// new_real(0.00324)
1580/// }
1581/// ```
1582/// ```q
1583/// q)reality: `libapi_examples 2: (`create_real; 1);
1584/// q)reality[]
1585/// 0.00324e
1586/// ```
1587#[inline]
1588pub fn new_real(real: F) -> K {
1589 unsafe { native::ke(real) }
1590}
1591
1592/// Constructor of q float object. Relabeling of `kf`.
1593/// # Example
1594/// ```
1595/// use kdbplus::api::*;
1596///
1597/// #[no_mangle]
1598/// pub extern "C" fn create_float(_: K) -> K{
1599/// new_float(-6302.620)
1600/// }
1601/// ```
1602/// ```q
1603/// q)coffee_float: `libapi_examples 2: (`create_float; 1);
1604/// q)coffee_float[]
1605/// -6302.62
1606/// ```
1607#[inline]
1608pub fn new_float(float: F) -> K {
1609 unsafe { native::kf(float) }
1610}
1611
1612/// Constructor of q char object. Relabeling of `kc`.
1613/// # Example
1614/// ```no_run
1615/// use kdbplus::api::*;
1616///
1617/// #[no_mangle]
1618/// pub extern "C" fn create_char2(_: K) -> K{
1619/// new_char('t')
1620/// }
1621/// ```
1622/// ```q
1623/// q)heavy: `libapi_examples 2: (`create_char2; 1);
1624/// q)heavy[]
1625/// "t"
1626/// ```
1627#[inline]
1628pub fn new_char(character: char) -> K {
1629 unsafe { native::kc(character as I) }
1630}
1631
1632/// Constructor of q symbol object. Relabeling of `ks`.
1633/// # Example
1634/// ```no_run
1635/// use kdbplus::api::*;
1636///
1637/// #[no_mangle]
1638/// pub extern "C" fn create_symbol2(_: K) -> K{
1639/// new_symbol("symbolic")
1640/// }
1641/// ```
1642/// ```q
1643/// q)hard: `libapi_examples 2: (`create_symbol2; 1);
1644/// q)hard[]
1645/// `symbolic
1646/// q)`symbolic ~ hard[]
1647/// 1b
1648/// ```
1649#[inline]
1650pub fn new_symbol(symbol: &str) -> K {
1651 unsafe { native::ks(str_to_S!(symbol)) }
1652}
1653
1654/// Constructor of q timestamp from elapsed time in nanoseconds since kdb+ epoch (`2000.01.01`). Relabeling of `ktj`.
1655/// ```no_run
1656/// use kdbplus::api::*;
1657///
1658/// #[no_mangle]
1659/// pub extern "C" fn create_timestamp2(_: K) -> K{
1660/// // 2015.03.16D00:00:00:00.000000000
1661/// new_timestamp(479779200000000000)
1662/// }
1663/// ```
1664/// ```q
1665/// q)stamp: `libapi_examples 2: (`create_timestamp2; 1);
1666/// q)stamp[]
1667/// 2015.03.16D00:00:00.000000000
1668/// ```
1669#[inline]
1670pub fn new_timestamp(nanoseconds: J) -> K {
1671 unsafe { native::ktj(qtype::TIMESTAMP_ATOM as I, nanoseconds) }
1672}
1673
1674/// Create a month object from the number of months since kdb+ epoch (`2000.01.01`).
1675/// This is a complememtal constructor of missing month type.
1676/// # Example
1677/// ```no_run
1678/// use kdbplus::api::*;
1679///
1680/// #[no_mangle]
1681/// pub extern "C" fn create_month(_: K) -> K{
1682/// // 2010.07m
1683/// new_month(126)
1684/// }
1685/// ```
1686/// ```q
1687/// q)create_month: `libapi_examples 2: (`create_month; 1);
1688/// q)create_month[]
1689/// 2010.07m
1690/// ```
1691#[inline]
1692pub fn new_month(months: I) -> K {
1693 unsafe {
1694 let month = native::ka(qtype::MONTH_ATOM as I);
1695 (*month).value.int = months;
1696 month
1697 }
1698}
1699
1700/// Constructor of q date object. Relabeling of `kd`.
1701/// # Example
1702/// ```no_run
1703/// use kdbplus::api::*;
1704///
1705/// #[no_mangle]
1706/// pub extern "C" fn create_date(_: K) -> K{
1707/// // 1999.12.25
1708/// new_date(-7)
1709/// }
1710/// ```
1711/// ```q
1712/// q)nostradamus: `libapi_examples 2: (`create_date; 1);
1713/// q)nostradamus[]
1714/// 1999.12.25
1715/// ```
1716#[inline]
1717pub fn new_date(days: I) -> K {
1718 unsafe { native::kd(days) }
1719}
1720
1721/// Constructor of q datetime object from the number of days since kdb+ epoch (`2000.01.01`). Relabeling of `kz`.
1722/// ```no_run
1723/// use kdbplus::api::*;
1724///
1725/// #[no_mangle]
1726/// pub extern "C" fn create_datetime(_: K) -> K{
1727/// // 2015.03.16T12:00:00:00.000
1728/// new_datetime(5553.5)
1729/// }
1730/// ```
1731/// ```q
1732/// q)omega_date: libc_api_examples 2: (`create_datetime; 1);
1733/// q)omega_date[]
1734/// 2015.03.16T12:00:00.000
1735/// ```
1736#[inline]
1737pub fn new_datetime(days: F) -> K {
1738 unsafe { native::kz(days) }
1739}
1740
1741/// Constructor of q timespan object from nanoseconds. Relabeling of `ktj`.
1742/// ```no_run
1743/// use kdbplus::api::*;
1744///
1745/// #[no_mangle]
1746/// pub extern "C" fn create_timespan2(_: K) -> K{
1747/// // -1D01:30:00.001234567
1748/// new_timespan(-91800001234567)
1749/// }
1750/// ```
1751/// ```q
1752/// q)duration: libc_api_examples 2: (`create_timespan2; 1);
1753/// q)duration[]
1754/// -1D01:30:00.001234567
1755/// ```
1756#[inline]
1757pub fn new_timespan(nanoseconds: J) -> K {
1758 unsafe { native::ktj(qtype::TIMESPAN_ATOM as I, nanoseconds) }
1759}
1760
1761/// Create a month object. This is a complememtal constructor of
1762/// missing minute type.
1763/// # Example
1764/// ```no_run
1765/// use kdbplus::api::*;
1766///
1767/// #[no_mangle]
1768/// pub extern "C" fn create_minute(_: K) -> K{
1769/// // 10:40
1770/// new_minute(640)
1771/// }
1772/// ```
1773/// ```q
1774/// q)minty: `libapi_examples 2: (`create_minute; 1);
1775/// q)minty[]
1776/// 10:40
1777/// ```
1778#[inline]
1779pub fn new_minute(minutes: I) -> K {
1780 unsafe {
1781 let minute = native::ka(qtype::MINUTE_ATOM as I);
1782 (*minute).value.int = minutes;
1783 minute
1784 }
1785}
1786
1787/// Create a month object. This is a complememtal constructor of
1788/// missing second type.
1789/// # Example
1790/// ```no_run
1791/// use kdbplus::api::*;
1792///
1793/// #[no_mangle]
1794/// pub extern "C" fn create_second(_: K) -> K{
1795/// // -02:00:00
1796/// new_second(-7200)
1797/// }
1798/// ```
1799/// ```q
1800/// q)third: `libapi_examples 2: (`create_second; 1);
1801/// q)third[]
1802/// -02:00:00
1803/// ```
1804#[inline]
1805pub fn new_second(seconds: I) -> K {
1806 unsafe {
1807 let second = native::ka(qtype::SECOND_ATOM as I);
1808 (*second).value.int = seconds;
1809 second
1810 }
1811}
1812
1813/// Constructor of q time object. Relabeling of `kt`.
1814/// # Example
1815/// ```no_run
1816/// use kdbplus::api::*;
1817///
1818/// #[no_mangle]
1819/// pub extern "C" fn create_time(_: K) -> K{
1820/// // -01:30:00.123
1821/// new_time(-5400123)
1822/// }
1823/// ```
1824/// ```q
1825/// q)ancient: libc_api_examples 2: (`create_time; 1);
1826/// q)ancient[]
1827/// -01:30:00.123
1828/// ```
1829#[inline]
1830pub fn new_time(milliseconds: I) -> K {
1831 unsafe { native::kt(milliseconds) }
1832}
1833
1834/// Constructor of q enum object. This is a complememtal constructor of
1835/// missing second type.
1836/// # Example
1837/// ```no_run
1838/// use kdbplus::api::*;
1839///
1840/// #[no_mangle]
1841/// pub extern "C" fn create_enum(source: K, index: K) -> K{
1842/// // Error if the specified enum source does not exist or it is not a symbol list or the index is out of enum range
1843/// new_enum(source.get_str().unwrap(), index.get_long().unwrap())
1844/// }
1845/// ```
1846/// ```q
1847/// q)enumerate: libc_api_examples 2: (`create_enum; 2);
1848/// q)sym: `a`b`c
1849/// q)enumerate["sym"; 1]
1850/// `sym$`b
1851/// q)enumerate["sym"; 3]
1852/// 'index out of enum range
1853/// [0] enumerate["sym"; 3]
1854/// ^
1855/// q)enumerate["som"; 0]
1856/// 'som
1857/// [1] som
1858/// ^
1859/// q))\
1860/// q)som:til 3
1861/// q)enumerate["som"; 0]
1862/// 'enum must be cast to symbol list
1863/// [0] enumerate["som"; 0]
1864/// ^
1865/// q)som:`a`b
1866/// q)enumerate["som"; 0]
1867/// `som$`a
1868/// ```
1869#[inline]
1870pub fn new_enum(source: &str, index: J) -> K {
1871 let sym = unsafe { native::k(0, str_to_S!(source), KNULL) };
1872 if unsafe { (*sym).qtype } == qtype::ERROR {
1873 // Error. Specified sym does not exist
1874 sym
1875 } else if unsafe { (*sym).qtype } != qtype::SYMBOL_LIST {
1876 // sym is not a symbol list
1877 unsafe {
1878 native::r0(sym);
1879 native::krr(null_terminated_str_to_const_S(
1880 "enum must be cast to symbol list\0",
1881 ))
1882 }
1883 } else if unsafe { (*sym).value.list.n } <= index {
1884 // Index is out of sym range
1885 unsafe {
1886 native::r0(sym);
1887 native::krr(null_terminated_str_to_const_S("index out of enum range\0"))
1888 }
1889 } else {
1890 let function = format!("{{`{}${} x}}", source, source);
1891 unsafe {
1892 native::r0(sym);
1893 native::k(0, str_to_S!(function.as_str()), native::kj(index), KNULL)
1894 }
1895 }
1896}
1897
1898/// Constructor of q simple list.
1899/// # Example
1900/// See the example of [`new_dictionary`](fn.new_dictionary.html).
1901#[inline]
1902pub fn new_list(qtype: i8, length: J) -> K {
1903 unsafe { native::ktn(qtype as I, length) }
1904}
1905
1906/// Constructor of q string object.
1907/// # Example
1908/// ```no_run
1909/// use kdbplus::api::*;
1910///
1911/// #[no_mangle]
1912/// pub extern "C" fn create_string(_: K) -> K{
1913/// new_string("this is a text.")
1914/// }
1915/// ```
1916/// ```q
1917/// q)text: libc_api_examples 2: (`create_string; 1);
1918/// q)text[]
1919/// "this is a text."
1920/// ```
1921#[inline]
1922pub fn new_string(string: &str) -> K {
1923 unsafe { native::kp(str_to_S!(string)) }
1924}
1925
1926/// Constructor if q string object with a fixed length.
1927/// # Example
1928/// ```no_run
1929/// use kdbplus::api::*;
1930///
1931/// #[no_mangle]
1932/// pub extern "C" fn create_string2(_: K) -> K{
1933/// new_string_n("The meeting was too long and I felt it s...", 24)
1934/// }
1935/// ```
1936/// ```q
1937/// q)speak_inwardly: libc_api_examples 2: (`create_string2; 1);
1938/// q)speak_inwardly[]
1939/// "The meeting was too long"
1940/// ```
1941#[inline]
1942pub fn new_string_n(string: &str, length: J) -> K {
1943 unsafe { native::kpn(str_to_S!(string), length) }
1944}
1945
1946/// Constructor of q dictionary object.
1947/// # Example
1948/// ```no_run
1949/// use kdbplus::api::*;
1950/// use kdbplus::qtype;
1951///
1952/// #[no_mangle]
1953/// pub extern "C" fn create_dictionary() -> K{
1954/// let keys=new_list(qtype::INT_LIST, 2);
1955/// keys.as_mut_slice::<I>()[0..2].copy_from_slice(&[0, 1]);
1956/// let values=new_list(qtype::COMPOUND_LIST, 2);
1957/// let date_list=new_list(qtype::DATE_LIST, 3);
1958/// // 2000.01.01 2000.01.02 2000.01.03
1959/// date_list.as_mut_slice::<I>()[0..3].copy_from_slice(&[0, 1, 2]);
1960/// let string=new_string("I'm afraid I would crash the application...");
1961/// values.as_mut_slice::<K>()[0..2].copy_from_slice(&[date_list, string]);
1962/// new_dictionary(keys, values)
1963/// }
1964/// ```
1965/// ```q
1966/// q)create_dictionary: `libapi_examples 2: (`create_dictionary; 1);
1967/// q)create_dictionary[]
1968/// 0| 2000.01.01 2000.01.02 2000.01.03
1969/// 1| "I'm afraid I would crash the application..."
1970/// ```
1971#[inline]
1972pub fn new_dictionary(keys: K, values: K) -> K {
1973 unsafe { native::xD(keys, values) }
1974}
1975
1976/// Constructor of q general null.
1977/// # Example
1978/// ```no_run
1979/// use kdbplus::qtype;
1980/// use kdbplus::api::*;
1981///
1982/// #[no_mangle]
1983/// pub extern "C" fn nullify(_: K) -> K{
1984/// let nulls=new_list(qtype::COMPOUND_LIST, 3);
1985/// let null_slice=nulls.as_mut_slice::<K>();
1986/// null_slice[0]=new_null();
1987/// null_slice[1]=new_string("null is not a general null");
1988/// null_slice[2]=new_null();
1989/// nulls
1990/// }
1991/// ```
1992/// ```q
1993/// q)void: `libapi_examples 2: (`nullify; 1);
1994/// q)void[]
1995/// ::
1996/// "null is not a general null"
1997/// ::
1998/// ```
1999#[inline]
2000pub fn new_null() -> K {
2001 unsafe {
2002 let null = native::ka(qtype::NULL as I);
2003 (*null).value.byte = 0;
2004 null
2005 }
2006}
2007
2008/// Constructor of q error. The input must be null-terminated.
2009/// # Example
2010/// ```no_run
2011/// use kdbplus::api::*;
2012///
2013/// pub extern "C" fn thai_kick(_: K) -> K{
2014/// new_error("Thai kick unconditionally!!\0")
2015/// }
2016/// ```
2017/// ```q
2018/// q)monstrous: `libapi_examples 2: (`thai_kick; 1);
2019/// q)monstrous[]
2020/// 'Thai kick unconditionally!!
2021/// [0] monstrous[]
2022/// ^
2023/// ```
2024#[inline]
2025pub fn new_error(message: &str) -> K {
2026 unsafe { native::krr(null_terminated_str_to_const_S(message)) }
2027}
2028
2029/// Similar to `new_error` but this function appends a system-error message to string `S` before passing it to internal `krr`.
2030/// The input must be null-terminated.
2031#[inline]
2032pub fn new_error_os(message: &str) -> K {
2033 unsafe { native::orr(null_terminated_str_to_const_S(message)) }
2034}
2035
2036/// Convert an error object into usual `K` object which has the error string in the field `symbol`.
2037/// # Example
2038/// ```no_run
2039/// use kdbplus::*;
2040/// use kdbplus::api::*;
2041///
2042/// extern "C" fn no_panick(func: K, args: K) -> K{
2043/// let result=error_to_string(apply(func, args));
2044/// if let Ok(error) = result.get_error_string(){
2045/// println!("FYI: {}", error);
2046/// // Decrement reference count of the error object which is no longer used.
2047/// decrement_reference_count(result);
2048/// KNULL
2049/// }
2050/// else{
2051/// result
2052/// }
2053/// }
2054/// ```
2055/// ```q
2056/// q)chill: `libapi_examples 2: (`no_panick; 2);
2057/// q)chill[$; ("J"; "42")]
2058/// success!
2059/// 42
2060/// q)chill[+; (1; `a)]
2061/// FYI: type
2062/// ```
2063/// # Note
2064/// If you intend to use the error string only in Rust side and not to return the value, you need
2065/// to decrement the reference count of the error object created by `error_to_string` as shown above.
2066/// If you want to propagate the error to q side after some operation, you can just return it (See the
2067/// example of [`is_error`](fn.is_error.html)).
2068///
2069/// # Warning
2070/// In q, an error is a 0 pointer. This causes a problem of false positive by `error_to_string`, i.e.,
2071/// `KNULL` is also catched as an error object and its type is set `qtype::ERROR`. In such a case you must NOT
2072/// return the catched object because it causes segmentation fault. If you want to check if the catched object
2073/// is an error and then return if it is, you should use [`is_error`](fn.is_error.html). If you want to use the
2074/// underlying error string of the catched object, you should use [`get_error_string`](trait.KUtility.html#tymethod.get_error_string).
2075#[inline]
2076pub fn error_to_string(error: K) -> K {
2077 unsafe { native::ee(error) }
2078}
2079
2080/// Judge if a catched object by [`error_to_string`](fn.error_to_string.html) is a genuine error object of type
2081/// `qtype::ERROR` (This means false positive of the `KNULL` case can be eliminated).
2082/// # Examples
2083/// ```no_run
2084/// use kdbplus::*;
2085/// use kdbplus::api::*;
2086///
2087/// fn love_even(arg: K) -> K{
2088/// if let Ok(int) = arg.get_int(){
2089/// if int % 2 == 0{
2090/// // Silent for even value
2091/// KNULL
2092/// }
2093/// else{
2094/// // Shout against odd value
2095/// new_error("great is the even value!!\0")
2096/// }
2097/// }
2098/// else{
2099/// // Pass through
2100/// increment_reference_count(arg)
2101/// }
2102/// }
2103///
2104/// #[no_mangle]
2105/// pub extern "C" fn propagate(arg: K) -> K{
2106/// let result=error_to_string(love_even(arg));
2107/// if is_error(result){
2108/// // Propagate the error
2109/// result
2110/// }
2111/// else if result.get_type() == qtype::ERROR{
2112/// // KNULL
2113/// println!("this is KNULL");
2114/// decrement_reference_count(result);
2115/// KNULL
2116/// }
2117/// else{
2118/// // Other
2119/// new_symbol("sonomama")
2120/// }
2121/// }
2122/// ```
2123/// ```q
2124/// q)convey: `libapi_examples 2: (`propagate; 1);
2125/// q)convey[7i]
2126/// 'great is the even value!!
2127/// q)convey[12i]
2128/// this is KNULL
2129/// q)convey[5.5]
2130/// `sonomama
2131/// ```
2132/// # Note
2133/// In this example `KNULL` is used as a returned value of the function called by another function to demonstrate
2134/// how `is_error` works. However, `KNULL` should not be used in such a way in order to avoid this kind of complexity.
2135/// To return a general null for inner functions, use [`new_null`](fn.new_null.html) instead.
2136#[inline]
2137pub fn is_error(catched: K) -> bool {
2138 (unsafe { (*catched).qtype } == qtype::ERROR) && !unsafe { (*catched).value.symbol }.is_null()
2139}
2140
2141//%% Symbol %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2142
2143/// Extract the first `n` chars from a character array and enumerate it internally.
2144/// This function must be used to add a character array as a symbol value to a symbol list.
2145/// The returned value is the same character array as the input.
2146/// # Example
2147/// See the example of [`flip`](fn.flip.html).
2148/// # Note
2149/// The reason why this function must be used is to enumerate the character array before handling
2150/// it as a q symbol type value. q/kdb+ is enumerating all symbol values to optimize comparison
2151/// or memory usage. On the other hand [`new_symbol`] does the enumeration internally and
2152/// therefore it does not need this function.
2153#[inline]
2154pub fn enumerate_n(string: S, n: I) -> S {
2155 unsafe { native::sn(string, n) }
2156}
2157
2158/// Enumerate a null-terminated character array internally. This function must be used
2159/// to add a character array as a symbol value to a symbol list. The returned value is
2160/// the same character array as the input.
2161/// # Example
2162/// See the example of [`flip`](fn.flip.html).
2163/// # Note
2164/// The reason why this function must be used is to enumerate the character array before handling
2165/// it as a q symbol type value. q/kdb+ is enumerating all symbol values to optimize comparison
2166/// or memory usage. On the other hand [`new_symbol`] does the enumeration internally and
2167/// therefore it does not need this function.
2168#[inline]
2169pub fn enumerate(string: S) -> S {
2170 unsafe { native::ss(string) }
2171}
2172
2173//%% Table %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2174
2175/// Constructor of q table object from a q dictionary object.
2176/// # Note
2177/// Basically this is a `flip` command of q. Hence the value of the dictionary must have
2178/// lists as its elements.
2179/// ```no_run
2180/// #[macro_use]
2181/// extern crate kdbplus;
2182/// use kdbplus::api::*;
2183/// use kdbplus::qtype;
2184///
2185/// #[no_mangle]
2186/// pub extern "C" fn create_table2(_: K) -> K{
2187/// // Build keys
2188/// let keys=new_list(qtype::SYMBOL_LIST, 2);
2189/// let keys_slice=keys.as_mut_slice::<S>();
2190/// keys_slice[0]=enumerate(str_to_S!("time"));
2191/// keys_slice[1]=enumerate_n(str_to_S!("temperature_and_humidity"), 11);
2192///
2193/// // Build values
2194/// let values=new_list(qtype::COMPOUND_LIST, 2);
2195/// let time=new_list(qtype::TIMESTAMP_LIST, 3);
2196/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
2197/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
2198/// let temperature=new_list(qtype::FLOAT_LIST, 3);
2199/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
2200/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
2201///
2202/// flip(new_dictionary(keys, values))
2203/// }
2204/// ```
2205/// ```q
2206/// q)climate_change: libc_api_examples 2: (`create_table2; 1);
2207/// q)climate_change[]
2208/// time temperature
2209/// -----------------------------------------
2210/// 2003.10.10D02:24:19.167018272 22.1
2211/// 2006.05.24D06:16:49.419710368 24.7
2212/// 2008.08.12D23:12:24.018691392 30.5
2213/// ```
2214#[inline]
2215pub fn flip(dictionary: K) -> K {
2216 match unsafe { (*dictionary).qtype } {
2217 qtype::DICTIONARY => unsafe { native::xT(dictionary) },
2218 _ => unsafe { native::krr(null_terminated_str_to_const_S("not a dictionary\0")) },
2219 }
2220}
2221
2222/// Constructor of simple q table object from a q keyed table object.
2223/// # Example
2224/// ```no_run
2225/// #[macro_use]
2226/// extern crate kdbplus;
2227/// use kdbplus::api::*;
2228/// use kdbplus::qtype;
2229///
2230/// #[no_mangle]
2231/// pub extern "C" fn create_table2(_: K) -> K{
2232/// // Build keys
2233/// let keys=new_list(qtype::SYMBOL_LIST, 2);
2234/// let keys_slice=keys.as_mut_slice::<S>();
2235/// keys_slice[0]=enumerate(str_to_S!("time"));
2236/// keys_slice[1]=enumerate_n(str_to_S!("temperature_and_humidity"), 11);
2237///
2238/// // Build values
2239/// let values=new_list(qtype::COMPOUND_LIST, 2);
2240/// let time=new_list(qtype::TIMESTAMP_LIST, 3);
2241/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
2242/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
2243/// let temperature=new_list(qtype::FLOAT_LIST, 3);
2244/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
2245/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
2246///
2247/// flip(new_dictionary(keys, values))
2248/// }
2249///
2250/// #[no_mangle]
2251/// pub extern "C" fn create_keyed_table(dummy: K) -> K{
2252/// enkey(create_table2(dummy), 1)
2253/// }
2254///
2255/// #[no_mangle]
2256/// pub extern "C" fn keyed_to_simple_table(dummy: K) -> K{
2257/// unkey(create_keyed_table(dummy))
2258/// }
2259/// ```
2260/// ```q
2261/// q)unkey: libc_api_examples 2: (`keyed_to_simple_table; 1);
2262/// q)unkey[]
2263/// time temperature
2264/// -----------------------------------------
2265/// 2003.10.10D02:24:19.167018272 22.1
2266/// 2006.05.24D06:16:49.419710368 24.7
2267/// 2008.08.12D23:12:24.018691392 30.5
2268/// ```
2269#[inline]
2270pub fn unkey(keyed_table: K) -> K {
2271 match unsafe { (*keyed_table).qtype } {
2272 qtype::DICTIONARY => unsafe { native::ktd(keyed_table) },
2273 _ => unsafe { native::krr(null_terminated_str_to_const_S("not a keyed table\0")) },
2274 }
2275}
2276
2277/// Constructor of q keyed table object.
2278/// # Parameters
2279/// - `table`: q table object to be enkeyed.
2280/// - `n`: The number of key columns from the left.
2281/// # Example
2282/// ```no_run
2283/// #[macro_use]
2284/// extern crate kdbplus;
2285/// use kdbplus::api::*;
2286/// use kdbplus::qtype;
2287///
2288/// #[no_mangle]
2289/// pub extern "C" fn create_table2(_: K) -> K{
2290/// // Build keys
2291/// let keys=new_list(qtype::SYMBOL_LIST, 2);
2292/// let keys_slice=keys.as_mut_slice::<S>();
2293/// keys_slice[0]=enumerate(str_to_S!("time"));
2294/// keys_slice[1]=enumerate_n(str_to_S!("temperature_and_humidity"), 11);
2295///
2296/// // Build values
2297/// let values=new_list(qtype::COMPOUND_LIST, 2);
2298/// let time=new_list(qtype::TIMESTAMP_LIST, 3);
2299/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
2300/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
2301/// let temperature=new_list(qtype::FLOAT_LIST, 3);
2302/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
2303/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
2304///
2305/// flip(new_dictionary(keys, values))
2306/// }
2307///
2308/// #[no_mangle]
2309/// pub extern "C" fn create_keyed_table(dummy: K) -> K{
2310/// enkey(create_table2(dummy), 1)
2311/// }
2312/// ```
2313/// ```q
2314/// q)locker: libc_api_examples 2: (`create_keyed_table; 1);
2315/// q)locker[]
2316/// time | temperature
2317/// -----------------------------| -----------
2318/// 2003.10.10D02:24:19.167018272| 22.1
2319/// 2006.05.24D06:16:49.419710368| 24.7
2320/// 2008.08.12D23:12:24.018691392| 30.5
2321/// ```
2322#[inline]
2323pub fn enkey(table: K, n: J) -> K {
2324 match unsafe { (*table).qtype } {
2325 qtype::TABLE => unsafe { native::knt(n, table) },
2326 _ => unsafe { native::krr(null_terminated_str_to_const_S("not a table\0")) },
2327 }
2328}
2329
2330//%% Reference Count %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2331
2332/// Decrement reference count of the q object. The decrement must be done when `k` function gets an error
2333/// object whose type is `qtype::ERROR` and when you created an object but do not intend to return it to
2334/// q side. See details on [the reference page](https://code.kx.com/q/interfaces/c-client-for-q/#managing-memory-and-reference-counting).
2335/// # Example
2336/// ```no_run
2337/// use kdbplus::api::*;
2338///
2339/// #[no_mangle]
2340/// pub extern "C" fn agriculture(_: K)->K{
2341/// // Produce an apple.
2342/// let fruit=new_symbol("apple");
2343/// // Sow the apple seed.
2344/// decrement_reference_count(fruit);
2345/// // Return null.
2346/// KNULL
2347/// }
2348/// ```
2349/// ```q
2350/// q)do_something: `libapi_examples 2: (`agriculture; 1);
2351/// q)do_something[]
2352/// q)
2353/// ```
2354#[inline]
2355pub fn decrement_reference_count(qobject: K) -> V {
2356 unsafe { native::r0(qobject) }
2357}
2358
2359/// Increment reference count of the q object. Increment must be done when you passed arguments
2360/// to Rust function and intends to return it to q side or when you pass some `K` objects to `k`
2361/// function and intend to use the argument after the call.
2362/// See details on [the reference page](https://code.kx.com/q/interfaces/c-client-for-q/#managing-memory-and-reference-counting).
2363/// # Example
2364/// ```no_run
2365/// #[macro_use]
2366/// extern crate kdbplus;
2367/// use kdbplus::api::*;
2368///
2369/// fn eat(apple: K){
2370/// println!("おいしい!");
2371/// }
2372///
2373/// #[no_mangle]
2374/// pub extern "C" fn satisfy_5000_men(apple: K) -> K{
2375/// for _ in 0..10{
2376/// eat(apple);
2377/// }
2378/// unsafe{native::k(0, str_to_S!("eat"), increment_reference_count(apple), KNULL);}
2379/// increment_reference_count(apple)
2380/// }
2381/// ```
2382/// ```q
2383/// q)eat:{[apple] show "Collect the clutter of apples!";}
2384/// q)bread_is_a_sermon: libc_api_examples 2: (`satisfy_5000_men; 1);
2385/// q)bread_is_a_sermon[`green_apple]
2386/// おいしい!
2387/// おいしい!
2388/// おいしい!
2389/// おいしい!
2390/// おいしい!
2391/// おいしい!
2392/// おいしい!
2393/// おいしい!
2394/// おいしい!
2395/// おいしい!
2396/// "Collect the clutter of apples!"
2397/// ```
2398#[inline]
2399pub fn increment_reference_count(qobject: K) -> K {
2400 unsafe { native::r1(qobject) }
2401}
2402
2403//%% Callback %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2404
2405/// Remove callback from the associated kdb+ socket and call `kclose`.
2406/// Return null if the socket is invalid or not the one which had been registered by `sd1`.
2407/// # Note
2408/// A function which calls this function must be executed at the exit of the process.
2409#[inline]
2410pub fn destroy_socket(socket: I) {
2411 unsafe {
2412 native::sd0(socket);
2413 }
2414}
2415
2416/// Remove callback from the associated kdb+ socket and call `kclose` if the given condition is satisfied.
2417/// Return null if the socket is invalid or not the one which had been registered by `sd1`.
2418/// # Note
2419/// A function which calls this function must be executed at the exit of the process.
2420#[inline]
2421pub fn destroy_socket_if(socket: I, condition: bool) {
2422 unsafe {
2423 native::sd0x(socket, condition as I);
2424 }
2425}
2426
2427/// Register callback to the associated kdb+ socket.
2428/// ```no_run
2429/// #[macro_use]
2430/// extern crate kdbplus;
2431/// use kdbplus::api::*;
2432/// use kdbplus::qtype;
2433///
2434/// static mut PIPE:[I; 2]=[-1, -1];
2435///
2436/// // Callback for some message queue.
2437/// extern "C" fn callback(socket: I)->K{
2438/// let mut buffer: [K; 1]=[0 as K];
2439/// unsafe{libc::read(socket, buffer.as_mut_ptr() as *mut V, 8)};
2440/// // Call `shout` function on q side with the received data.
2441/// let result=error_to_string(unsafe{native::k(0, str_to_S!("shout"), buffer[0], KNULL)});
2442/// if result.get_type() == qtype::ERROR{
2443/// eprintln!("Execution error: {}", result.get_symbol().unwrap());
2444/// decrement_reference_count(result);
2445/// };
2446/// KNULL
2447/// }
2448///
2449/// #[no_mangle]
2450/// pub extern "C" fn plumber(_: K) -> K{
2451/// if 0 != unsafe{libc::pipe(PIPE.as_mut_ptr())}{
2452/// return new_error("Failed to create pipe\0");
2453/// }
2454/// if KNULL == register_callback(unsafe{PIPE[0]}, callback){
2455/// return new_error("Failed to register callback\0");
2456/// }
2457/// // Lock symbol in a worker thread.
2458/// pin_symbol();
2459/// let handle=std::thread::spawn(move ||{
2460/// let mut precious=new_list(qtype::SYMBOL_LIST, 3);
2461/// let precious_array=precious.as_mut_slice::<S>();
2462/// precious_array[0]=enumerate(null_terminated_str_to_S("belief\0"));
2463/// precious_array[1]=enumerate(null_terminated_str_to_S("love\0"));
2464/// precious_array[2]=enumerate(null_terminated_str_to_S("hope\0"));
2465/// unsafe{libc::write(PIPE[1], std::mem::transmute::<*mut K, *mut V>(&mut precious), 8)};
2466/// });
2467/// handle.join().unwrap();
2468/// unpin_symbol();
2469/// KNULL
2470/// }
2471/// ```
2472/// ```q
2473/// q)shout:{[precious] -1 "What are the three largest elements?: ", .Q.s1 precious;};
2474/// q)fall_into_pipe: `libc_api_example 2: (`plumber; 1);
2475/// q)fall_into_pipe[]
2476/// What are the three largest elements?: `belief`love`hope
2477/// ```
2478#[inline]
2479pub fn register_callback(socket: I, function: extern "C" fn(I) -> K) -> K {
2480 unsafe { native::sd1(socket, function) }
2481}
2482
2483//%% Miscellaneous %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2484
2485/// Apply a function to q list object `.[func; args]`.
2486/// # Example
2487/// See the example of [`error_to_string`](fn.error_to_string.html).
2488#[inline]
2489pub fn apply(func: K, args: K) -> K {
2490 unsafe { native::dot(func, args) }
2491}
2492
2493/// Enable the remote threads to refer to the sym list in the main thread so that enumeration
2494/// of remotely created symbol values reain valid in the main thread after joining the
2495/// remote threads. This function must be used before starting any other threads if the
2496/// threads create symbol values. The previously set value is returned.
2497/// # Example
2498/// See the example of [`register_callback`](fn.register_callback.html).
2499#[inline]
2500pub fn pin_symbol() -> I {
2501 unsafe { native::setm(1) }
2502}
2503
2504/// Unlock the symbol list in the main thread. This function should be called after joining
2505/// threads.
2506/// # Example
2507/// See the example of [`register_callback`](fn.register_callback.html).
2508#[inline]
2509pub fn unpin_symbol() -> I {
2510 unsafe { native::setm(0) }
2511}
2512
2513/// Drop Rust object inside q. Passed as the first element of a foreign object.
2514/// # Parameters
2515/// - `obj`: List of (function to free the object; foreign object).
2516/// # Example
2517/// See the example of [`load_as_q_function`](fn.load_as_q_function.html).
2518pub fn drop_q_object(obj: K) -> K {
2519 let obj_slice = obj.as_mut_slice::<K>();
2520 // Take ownership of `K` object from a raw pointer and drop at the end of this scope.
2521 unsafe {
2522 let _ = Box::from_raw(obj_slice[1]);
2523 };
2524 // Fill the list with null.
2525 obj_slice.copy_from_slice(&[KNULL, KNULL]);
2526 obj
2527}
2528
2529/// Load C function as a q function (`K` object).
2530/// # Parameters
2531/// - `func`: A function takes a C function that would take `n` `K` objects as arguments and returns a `K` object.
2532/// - `n`: The number of arguments for the function.
2533/// # Example
2534/// ```no_run
2535/// #[macro_use]
2536/// extern crate kdbplus;
2537/// use kdbplus::api::*;
2538/// use kdbplus::qtype;
2539///
2540/// #[derive(Clone, Debug)]
2541/// struct Planet{
2542/// name: String,
2543/// population: i64,
2544/// water: bool
2545/// }
2546///
2547/// impl Planet{
2548/// /// Constructor of `Planet`.
2549/// fn new(name: &str, population: i64, water: bool) -> Self{
2550/// Planet{
2551/// name: name.to_string(),
2552/// population: population,
2553/// water: water
2554/// }
2555/// }
2556///
2557/// /// Description of the planet.
2558/// fn description(&self)->String{
2559/// let mut desc=format!("The planet {} is a beautiful planet where {} people reside.", self.name, self.population);
2560/// if self.water{
2561/// desc+=" Furthermore water is flowing on the surface of it.";
2562/// }
2563/// desc
2564/// }
2565/// }
2566///
2567/// /// Example of `set_type`.
2568/// #[no_mangle]
2569/// pub extern "C" fn eden(_: K) -> K{
2570/// let earth=Planet::new("earth", 7500_000_000, true);
2571/// let mut foreign=new_list(qtype::COMPOUND_LIST, 2);
2572/// let foreign_slice=foreign.as_mut_slice::<K>();
2573/// foreign_slice[0]=drop_q_object as K;
2574/// foreign_slice[1]=Box::into_raw(Box::new(earth)) as K;
2575/// // Set as foreign object.
2576/// foreign.set_type(qtype::FOREIGN);
2577/// foreign
2578/// }
2579///
2580/// extern "C" fn invade(planet: K, action: K) -> K{
2581/// let obj=planet.as_mut_slice::<K>()[1] as *const Planet;
2582/// println!("{:?}", unsafe{obj.as_ref()}.unwrap());
2583/// let mut desc=unsafe{obj.as_ref()}.unwrap().description();
2584/// if action.get_bool().unwrap(){
2585/// desc+=" You shall not curse what God blessed.";
2586/// }
2587/// else{
2588/// desc+=" I perceived I could find favor of God by blessing them.";
2589/// }
2590/// new_string(&desc)
2591/// }
2592///
2593/// /// Example of `load_as_q_function`.
2594/// #[no_mangle]
2595/// pub extern "C" fn probe(planet: K)->K{
2596/// // Return monadic function
2597/// unsafe{native::k(0, str_to_S!("{[func; planet] func[planet]}"), load_as_q_function(invade as *const V, 2), planet, KNULL)}
2598/// }
2599/// ```
2600/// ```q
2601/// q)eden: libc_api_example 2: (`eden; 1);
2602/// q)earth: eden[]
2603/// q)type earth
2604/// 112h
2605/// q)probe: libc_api_example 2: (`probe; 1);
2606/// q)invade: probe[earth];
2607/// q)\c 25 200
2608/// q)invade 1b
2609/// "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."
2610/// ```
2611#[inline]
2612pub fn load_as_q_function(func: *const V, n: J) -> K {
2613 unsafe { native::dl(func, n) }
2614}
2615
2616/// Convert ymd to the number of days from `2000.01.01`.
2617/// # Example
2618/// ```no_run
2619/// use kdbplus::api::*;
2620///
2621/// let days=ymd_to_days(2020, 4, 1);
2622/// assert_eq!(days, 7396);
2623/// ```
2624#[inline]
2625pub fn ymd_to_days(year: I, month: I, date: I) -> I {
2626 unsafe { native::ymd(year, month, date) }
2627}
2628
2629/// Convert the number of days from `2000.01.01` to a number expressed as `yyyymmdd`.
2630/// # Example
2631/// ```no_run
2632/// use kdbplus::api::*;
2633///
2634/// let number=days_to_ymd(7396);
2635/// assert_eq!(number, 20200401);
2636/// ```
2637#[inline]
2638pub fn days_to_ymd(days: I) -> I {
2639 unsafe { native::dj(days) }
2640}
2641
2642/// Convert a simple list to a compound list. Expected usage is to concatinate a simple list
2643/// with a different type of list.
2644/// # Example
2645/// ```no_run
2646/// use kdbplus::*;
2647/// use kdbplus::api::*;
2648///
2649/// #[no_mangle]
2650/// pub extern "C" fn drift(_: K)->K{
2651/// let simple=new_list(qtype::INT_LIST, 2);
2652/// simple.as_mut_slice::<I>().copy_from_slice(&[12, 34]);
2653/// let extra=new_list(qtype::COMPOUND_LIST, 2);
2654/// extra.as_mut_slice::<K>().copy_from_slice(&[new_symbol("vague"), new_int(-3000)]);
2655/// // Convert an integer list into a compound list
2656/// let mut compound = simple_to_compound(simple, "");
2657/// compound.append(extra).unwrap()
2658/// }
2659///
2660/// #[no_mangle]
2661/// pub extern "C" fn drift2(_: K)->K{
2662/// let simple=new_list(qtype::ENUM_LIST, 2);
2663/// simple.as_mut_slice::<J>().copy_from_slice(&[0_i64, 1]);
2664/// // Convert an enum indices into a compound list while creating enum values from the indices which are tied with
2665/// // an existing enum variable named "enum", i.e., Enum indices [0, 1] in the code are cast into `(enum[0]; enum[1])`.
2666/// let mut compound = simple_to_compound(simple, "enum");
2667/// // Add `enum2[2]`.
2668/// compound.push(new_enum("enum2", 2)).unwrap();
2669/// compound.push(new_month(3)).unwrap();
2670/// compound
2671/// }
2672/// ```
2673/// ```q
2674/// q)drift: LIBPATH_ (`drift; 1);
2675/// q)drift2: LIBPATH_ (`drift2; 1);
2676/// q)drift[]
2677/// 12i
2678/// 34i
2679/// `vague
2680/// -3000i
2681/// q)enum: `mashroom`broccoli`cucumber
2682/// q)enum2: `mackerel`swordfish`tuna
2683/// q)drift2[]
2684/// `enum$`mashroom
2685/// `enum$`broccoli
2686/// `enum2$`tuna
2687/// 2000.04m
2688/// ```
2689/// # Note
2690/// - To convert a list provided externally (i.e., passed from a q process), apply
2691/// [`increment_reference_count`](fn.increment_reference_count.html) before converting the list.
2692/// - Enum elements from different enum sources must be contained in a compound list. Therefore
2693/// this function intentionally restricts the number of enum sources to one so that user switches
2694/// a simple list to a compound list when the second enum sources are provided.
2695pub fn simple_to_compound(simple: K, enum_source: &str) -> K {
2696 let size = simple.len() as usize;
2697 let compound = new_list(qtype::COMPOUND_LIST, size as J);
2698 let compound_slice = compound.as_mut_slice::<K>();
2699 match simple.get_type() {
2700 qtype::BOOL_LIST => {
2701 let simple_slice = simple.as_mut_slice::<G>();
2702 for i in 0..size {
2703 compound_slice[i] = new_bool(simple_slice[i] as I);
2704 }
2705 }
2706 qtype::GUID_LIST => {
2707 let simple_slice = simple.as_mut_slice::<U>();
2708 for i in 0..size {
2709 compound_slice[i] = new_guid(simple_slice[i].guid);
2710 }
2711 }
2712 qtype::BYTE_LIST => {
2713 let simple_slice = simple.as_mut_slice::<G>();
2714 for i in 0..size {
2715 compound_slice[i] = new_byte(simple_slice[i] as I);
2716 }
2717 }
2718 qtype::SHORT_LIST => {
2719 let simple_slice = simple.as_mut_slice::<H>();
2720 for i in 0..size {
2721 compound_slice[i] = new_short(simple_slice[i] as I);
2722 }
2723 }
2724 qtype::INT_LIST => {
2725 let simple_slice = simple.as_mut_slice::<I>();
2726 for i in 0..size {
2727 compound_slice[i] = new_int(simple_slice[i]);
2728 }
2729 }
2730 qtype::LONG_LIST => {
2731 let simple_slice = simple.as_mut_slice::<J>();
2732 for i in 0..size {
2733 compound_slice[i] = new_long(simple_slice[i]);
2734 }
2735 }
2736 qtype::REAL_LIST => {
2737 let simple_slice = simple.as_mut_slice::<E>();
2738 for i in 0..size {
2739 compound_slice[i] = new_real(simple_slice[i] as F);
2740 }
2741 }
2742 qtype::FLOAT_LIST => {
2743 let simple_slice = simple.as_mut_slice::<F>();
2744 for i in 0..size {
2745 compound_slice[i] = new_float(simple_slice[i]);
2746 }
2747 }
2748 qtype::STRING => {
2749 let simple_slice = simple.as_mut_slice::<G>();
2750 for i in 0..size {
2751 compound_slice[i] = new_char(simple_slice[i] as char);
2752 }
2753 }
2754 qtype::SYMBOL_LIST => {
2755 let simple_slice = simple.as_mut_slice::<S>();
2756 for i in 0..size {
2757 compound_slice[i] = new_symbol(S_to_str(simple_slice[i]));
2758 }
2759 }
2760 qtype::TIMESTAMP_LIST => {
2761 let simple_slice = simple.as_mut_slice::<J>();
2762 for i in 0..size {
2763 compound_slice[i] = new_timestamp(simple_slice[i]);
2764 }
2765 }
2766 qtype::DATE_LIST => {
2767 let simple_slice = simple.as_mut_slice::<I>();
2768 for i in 0..size {
2769 compound_slice[i] = new_date(simple_slice[i]);
2770 }
2771 }
2772 qtype::TIME_LIST => {
2773 let simple_slice = simple.as_mut_slice::<I>();
2774 for i in 0..size {
2775 compound_slice[i] = new_time(simple_slice[i]);
2776 }
2777 }
2778 qtype::ENUM_LIST => {
2779 let simple_slice = simple.as_mut_slice::<J>();
2780 for i in 0..size {
2781 compound_slice[i] = new_enum(enum_source, simple_slice[i]);
2782 }
2783 }
2784 _ => {
2785 decrement_reference_count(compound);
2786 return new_error("not a simple list\0");
2787 }
2788 }
2789 // Free simple list
2790 decrement_reference_count(simple);
2791 compound
2792}