Skip to main content

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}