Skip to main content

kdb_plus_fixed/ipc/
mod.rs

1//! This `ipc` module provides an interface to interact with q/kdb+ via IPC. The expected usage is to send a (text) query to q/kdb+ process
2//!  from Rust client and receive its response. Query to kdb+ is supported in two ways:
3//!
4//! - text query
5//! - functional query which is represented by a compound list of kdb+ ([See detail of IPC](https://code.kx.com/q4m3/11_IO/#116-interprocess-communication)).
6//!
7//! Compression/decompression of messages is also implemented following [kdb+ implementation](https://code.kx.com/q/basics/ipc/#compression).
8//!
9//! As for connect method, usually client interfaces of q/kdb+ do not provide a listener due to its protocol. However, sometimes Rust process is
10//!  connecting to upstream and q/kdb+ starts afterward or is restarted more frequently. Then providing a listener method is a natural direction
11//!  and it was achieved here. Following ways are supported to connect to kdb+:
12//!
13//! - TCP
14//! - TLS
15//! - Unix domain socket
16//!
17//! Furthermore, in order to improve inter-operatability some casting, getter and setter methods are provided.
18//!
19//! ## Environmentl Variables
20//!
21//! This crate uses q-native or crate-specific environmental variables.
22//!
23//! - `KDBPLUS_ACCOUNT_FILE`: A file path to a credential file which an acceptor loads in order to manage access from a q client. This file contains
24//!   a user name and SHA-1 hashed password in each line which are delimited by `':'` without any space. For example, a file containing two credentials
25//!   `"mattew:oracle"` and `"reluctant:slowday"` looks like this:
26//!
27//!      ```bash
28//!       mattew:431364b6450fc47ccdbf6a2205dfdb1baeb79412
29//!       reluctant:d03f5cc1cdb11a77410ee34e26ca1102e67a893c
30//!      ```
31//!       
32//!     The hashed password can be generated with q using a function `.Q.sha1`:
33//!  
34//!      ```q
35//!       q).Q.sha1 "slowday"
36//!       0xd03f5cc1cdb11a77410ee34e26ca1102e67a893c
37//!      ```
38//!
39//! - `KDBPLUS_TLS_KEY_FILE` and `KDBPLUS_TLS_KEY_FILE_SECRET`: The pkcs12 file and its password which TLS acceptor uses.
40//! - `QUDSPATH` (optional): q-native environmental variable to define an astract namespace. This environmental variable is used by UDS acceptor too.
41//!   The abstract nameapace will be `@${QUDSPATH}/kx.[server process port]` if this environmental variable is defined. Otherwise it will be `@/tmp/kx.[server process port]`.
42//!
43//! *Notes:*
44//!
45//! - Messages will be sent with OS native endian.
46//! - When using this crate for a TLS client you need to set two environmental variables `KX_SSL_CERT_FILE` and `KX_SSL_KEY_FILE` on q side to make q/kdb+
47//!   to work as a TLS server. For details, see [the KX website](https://code.kx.com/q/kb/ssl/).
48//!
49//! ## Type Mapping
50//!
51//! All types are expressed as `K` struct which is quite similar to the `K` struct of `api` module but its structure is optimized for IPC
52//!  usage and for convenience to interact with. The table below shows the input types of each q type which is used to construct `K` object.
53//!  Note that the input type can be different from the inner type. For example, timestamp has an input type of `chrono::DateTime<Utc>` but
54//!  the inner type is `i64` denoting an elapsed time in nanoseconds since `2000.01.01D00:00:00`.
55//!
56//! | q                | Rust                                              |
57//! |------------------|---------------------------------------------------|
58//! | `bool`           | `bool`                                            |
59//! | `GUID`           | `[u8; 16]`                                        |
60//! | `byte`           | `u8`                                              |
61//! | `short`          | `i16`                                             |
62//! | `int`            | `i32`                                             |
63//! | `long`           | `i64`                                             |
64//! | `real`           | `f32`                                             |
65//! | `float`          | `f64`                                             |
66//! | `char`           | `char`                                            |
67//! | `symbol`         | `String`                                          |
68//! | `timestamp`      | `chrono::DateTime<Utc>`                           |
69//! | `month`          | `chrono::NaiveDate`                               |
70//! | `date`           | `chrono::NaiveDate`                               |
71//! | `datetime`       | `chrono::DateTime<Utc>`                           |
72//! | `timespan`       | `chrono::Duration`                                |
73//! | `minute`         | `chrono::Duration`                                |
74//! | `second`         | `chrono::Duration`                                |
75//! | `time`           | `chrono::Duration`                                |
76//! | `list`           | `Vec<Item>` (`Item` is a corrsponding type above) |
77//! | `compound list`  | `Vec<K>`                                          |
78//! | `table`          | `Vec<K>`                                          |
79//! | `dictionary`     | `Vec<K>`                                          |
80//! | `null`           | `()`                                              |
81//!
82//! ## Examples
83//!
84//! ### Client
85//!
86//! ```rust
87//! use kdbplus::qattribute;
88//! use kdbplus::ipc::*;
89//!
90//! #[tokio::main(flavor = "multi_thread", worker_threads = 2)]
91//! async fn main() -> Result<()> {
92//!     // Connect to qprocess running on localhost:5000 via UDS
93//!     let mut socket = QStream::connect(ConnectionMethod::UDS, "", 5000_u16, "ideal:person").await?;
94//!     println!("Connection type: {}", socket.get_connection_type());
95//!
96//!     // Set remote function with an asynchronous text form message
97//!     socket.send_async_message(&"collatz:{[n] seq:enlist n; while[not n = 1; seq,: n:$[n mod 2; 1 + 3 * n; `long$n % 2]]; seq}").await?;
98//!
99//!     // Send a text form emessage synchronously
100//!     let mut result = socket.send_sync_message(&"collatz[12]").await?;
101//!     println!("collatz[12]: {}", result);
102//!
103//!     result = socket.send_sync_message(&"collatz[`a]").await?;
104//!     println!("collatz[`a]: {}", result);
105//!
106//!     // Send a functional form message synchronously.
107//!     let mut message = K::new_compound_list(vec![
108//!         K::new_symbol(String::from("collatz")),
109//!         K::new_long(100),
110//!     ]);
111//!     result = socket.send_sync_message(&message).await?;
112//!     println!("collatz[100]: {}", result);
113//!
114//!     // Modify the message to (`collatz; 20)
115//!     message.pop().unwrap();
116//!     message.push(&K::new_long(20)).unwrap();
117//!     result = socket.send_sync_message(&message).await?;
118//!     println!("collatz[20]: {}", result);
119//!
120//!     // Send a functional form message asynchronous query.
121//!     message = K::new_compound_list(vec![
122//!         K::new_string(String::from("show"), qattribute::NONE),
123//!         K::new_symbol(String::from("goodbye")),
124//!     ]);
125//!     socket.send_async_message(&message).await?;
126//!
127//!     socket.shutdown().await?;
128//!
129//!     Ok(())
130//! }
131//!```
132//! ### Listener
133//!
134//! ```no_run
135//! use std::io;
136//! use kdbplus::ipc::*;
137//!
138//! #[tokio::main]
139//! async fn main() -> Result<()> {
140//!     // Start listenening over TCP at the port 7000 with authentication enabled.
141//!     let mut socket_tcp = QStream::accept(ConnectionMethod::TCP, "127.0.0.1", 7000).await?;
142//!
143//!     // Send a query with the socket.
144//!     let greeting = socket_tcp.send_sync_message(&"string `Hello").await?;
145//!     println!("Greeting: {}", greeting);
146//!
147//!     socket_tcp.shutdown().await?;
148//!
149//!     Ok(())
150//! }
151//! ```
152//!
153//! Then q client can connect to this acceptor with the acceptor's host, port and the credential configured in `KDBPLUS_ACCOUNT_FILE`:
154//!
155//! ```q
156//! q)h:hopen `::7000:reluctant:slowday
157//! ```
158
159//++++++++++++++++++++++++++++++++++++++++++++++++++//
160// >> Settings
161//++++++++++++++++++++++++++++++++++++++++++++++++++//
162
163#![allow(non_upper_case_globals)]
164#![allow(non_camel_case_types)]
165#![allow(non_snake_case)]
166#![allow(clippy::borrow_interior_mutable_const)]
167#![allow(clippy::declare_interior_mutable_const)]
168
169//++++++++++++++++++++++++++++++++++++++++++++++++++//
170// >> Load Libraries
171//++++++++++++++++++++++++++++++++++++++++++++++++++//
172
173pub mod error;
174
175use super::{qattribute, qinf_base, qninf_base, qnull_base, qtype};
176use chrono::prelude::*;
177use chrono::Duration;
178use error::Error;
179use std::any::Any;
180use std::fmt;
181use std::result::Result as StdResult;
182
183//++++++++++++++++++++++++++++++++++++++++++++++++++//
184// >> Structs
185//++++++++++++++++++++++++++++++++++++++++++++++++++//
186
187pub type Result<T> = StdResult<T, Error>;
188
189//++++++++++++++++++++++++++++++++++++++++++++++++++//
190// >> Global Variables
191//++++++++++++++++++++++++++++++++++++++++++++++++++//
192
193//%% kdb+ Offset %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
194
195/// 1 day in nano second.
196pub const ONE_DAY_NANOS: i64 = 86400000000000;
197
198/// 1 day in milli second.
199pub const ONE_DAY_MILLIS: i64 = 86400000;
200
201/// 2000.01.01 (kdb+ epoch) - 1970.01.01 in month.
202pub const KDB_MONTH_OFFSET: i32 = 360;
203
204/// 2000.01.01 (kdb+ epoch) - 1970.01.01 in day.
205pub const KDB_DAY_OFFSET: i32 = 10957;
206
207/// 2000.01.01 (kdb+ epoch) - 1970.01.01 in nanosecond.
208pub const KDB_TIMESTAMP_OFFSET: i64 = 946684800000000000;
209
210//%% Null & Infinity %%vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
211
212pub mod qnull {
213    //! This module provides a list of q null values set on Rust process and used for IPC. The motivation
214    //!  to contain them in a module is to tie them up as related items rather than scattered values.
215    //!  Hence user should use these indicators with `qnull::` prefix, e.g., `qnull::FLOAT`.
216
217    use super::qnull_base;
218    use chrono::prelude::*;
219    use chrono::Duration;
220    use once_cell::sync::Lazy;
221
222    /// Null value of GUID (`0Ng`).
223    /// # Example
224    /// ```
225    /// use kdbplus::ipc::*;
226    ///
227    /// let q_guid_null = K::new_guid(qnull::GUID);
228    /// assert_eq!(
229    ///     format!("{}", q_guid_null),
230    ///     String::from("00000000-0000-0000-0000-000000000000")
231    /// );
232    /// ```
233    pub const GUID: [u8; 16] = [0_u8; 16];
234
235    /// Null value of short (`0Nh`).
236    /// # Example
237    /// ```
238    /// use kdbplus::ipc::*;
239    ///
240    /// let q_short_null = K::new_short(qnull::SHORT);
241    /// assert_eq!(format!("{}", q_short_null), String::from("0Nh"));
242    /// ```
243    pub const SHORT: i16 = qnull_base::H;
244
245    /// Null value of int (`0Ni`).
246    /// # Example
247    /// ```
248    /// use kdbplus::ipc::*;
249    ///
250    /// let q_int_null = K::new_int(qnull::INT);
251    /// assert_eq!(format!("{}", q_int_null), String::from("0Ni"));
252    /// ```
253    pub const INT: i32 = qnull_base::I;
254
255    /// Null value of long (`0N`).
256    /// # Example
257    /// ```
258    /// use kdbplus::ipc::*;
259    ///
260    /// let q_long_null = K::new_long(qnull::LONG);
261    /// assert_eq!(format!("{}", q_long_null), String::from("0N"));
262    /// ```
263    pub const LONG: i64 = qnull_base::J;
264
265    /// Null value of real (`0Ne`).
266    /// # Example
267    /// ```
268    /// use kdbplus::ipc::*;
269    ///
270    /// let q_real_null = K::new_real(qnull::REAL);
271    /// assert_eq!(format!("{}", q_real_null), String::from("0Ne"));
272    /// ```
273    pub const REAL: f32 = qnull_base::E;
274
275    /// Null value of float (`0n`).
276    /// # Example
277    /// ```
278    /// use kdbplus::ipc::*;
279    ///
280    /// let q_float_null = K::new_float(qnull::FLOAT);
281    /// assert_eq!(format!("{}", q_float_null), String::from("0n"));
282    /// ```
283    pub const FLOAT: f64 = qnull_base::F;
284
285    /// Null value of char (`" "`).
286    /// # Example
287    /// ```
288    /// use kdbplus::ipc::*;
289    ///
290    /// let q_char_null = K::new_char(qnull::CHAR);
291    /// assert_eq!(format!("{}", q_char_null), String::from("\" \""));
292    /// ```
293    pub const CHAR: char = qnull_base::C;
294
295    /// Null value of symbol (<code>`</code>).
296    /// # Example
297    /// ```
298    /// use kdbplus::ipc::*;
299    ///
300    /// let q_symbol_null = K::new_symbol(qnull::SYMBOL);
301    /// assert_eq!(format!("{}", q_symbol_null), String::from("`"));
302    /// ```
303    pub const SYMBOL: String = String::new();
304
305    /// Null value of timestamp (`0Np`).
306    /// # Example
307    /// ```
308    /// use kdbplus::ipc::*;
309    ///
310    /// let q_timestamp_null = K::new_timestamp(*qnull::TIMESTAMP);
311    /// assert_eq!(format!("{}", q_timestamp_null), String::from("0Np"));
312    /// ```
313    /// # Note
314    /// The range of timestamp in Rust is wider than in q.
315    pub const TIMESTAMP: Lazy<DateTime<Utc>> = Lazy::new(|| {
316        NaiveDate::from_ymd_opt(1707, 9, 22)
317            .unwrap()
318            .and_hms_nano_opt(0, 12, 43, 145224192)
319            .unwrap()
320            .and_local_timezone(Utc)
321            .unwrap()
322    });
323
324    /// Null value of month (`0Nm`).
325    /// # Example
326    /// ```
327    /// use kdbplus::ipc::*;
328    ///
329    /// let q_month_null = K::new_month(qnull::MONTH);
330    /// assert_eq!(format!("{}", q_month_null), String::from("0Nm"));
331    /// ```
332    /// # Note
333    /// The range of month in Rust is narrower than in q.
334    pub const MONTH: NaiveDate = NaiveDate::MIN;
335
336    /// Null valueo of date (`0Nd`).
337    /// # Example
338    /// ```
339    /// use kdbplus::ipc::*;
340    ///
341    /// let q_date_null = K::new_date(qnull::DATE);
342    /// assert_eq!(format!("{}", q_date_null), String::from("0Nd"));
343    /// ```
344    /// # Note
345    /// The range of date in Rust is narrower than in q.
346    pub const DATE: NaiveDate = NaiveDate::MIN;
347
348    /// Null value of datetime (`0Nz`).
349    /// # Example
350    /// ```
351    /// use kdbplus::ipc::*;
352    ///
353    /// let q_datetime_null = K::new_datetime(qnull::DATETIME);
354    /// assert_eq!(format!("{}", q_datetime_null), String::from("0Nz"));
355    /// ```
356    /// # Note
357    /// The range of datetime in Rust is narrower than in q.
358    pub const DATETIME: DateTime<Utc> = DateTime::<Utc>::MIN_UTC;
359
360    /// Null value of timespan (`0Nn`).
361    /// # Example
362    /// ```
363    /// use kdbplus::ipc::*;
364    ///
365    /// let q_timespan_null = K::new_timespan(*qnull::TIMESPAN);
366    /// assert_eq!(format!("{}", q_timespan_null), String::from("0Nn"));
367    /// ```
368    pub const TIMESPAN: Lazy<Duration> = Lazy::new(|| Duration::nanoseconds(qnull_base::J));
369
370    /// Null value of minute (`0Nu`).
371    /// # Example
372    /// ```
373    /// use kdbplus::ipc::*;
374    ///
375    /// let q_minute_null = K::new_minute(*qnull::MINUTE);
376    /// assert_eq!(format!("{}", q_minute_null), String::from("0Nu"));
377    /// ```
378    pub const MINUTE: Lazy<Duration> = Lazy::new(|| Duration::minutes(qnull_base::I as i64));
379
380    /// Null value of second (`0Nv`).
381    /// # Example
382    /// ```
383    /// use kdbplus::ipc::*;
384    ///
385    /// let q_second_null = K::new_second(*qnull::SECOND);
386    /// assert_eq!(format!("{}", q_second_null), String::from("0Nv"));
387    /// ```
388    pub const SECOND: Lazy<Duration> = Lazy::new(|| Duration::seconds(qnull_base::I as i64));
389
390    /// Null value of time (`0Nt`).
391    /// # Example
392    /// ```
393    /// use kdbplus::ipc::*;
394    ///
395    /// let q_time_null = K::new_time(*qnull::TIME);
396    /// assert_eq!(format!("{}", q_time_null), String::from("0Nt"));
397    /// ```
398    pub const TIME: Lazy<Duration> = Lazy::new(|| Duration::milliseconds(qnull_base::I as i64));
399}
400
401pub mod qinf {
402    //! This module provides a list of q infinite values set on Rust process and used for IPC.
403    //!  The motivation to contain them in a module is to tie them up as related items rather
404    //!  than scattered values. Hence user should use these indicators with `qnull::` prefix, e.g., `qnull::FLOAT`.
405
406    use super::qinf_base;
407    use chrono::prelude::*;
408    use chrono::Duration;
409    use once_cell::sync::Lazy;
410
411    /// Infinity value of short (`0Wh`).
412    /// # Example
413    /// ```
414    /// use kdbplus::ipc::*;
415    ///
416    /// let q_short_inf = K::new_short(qinf::SHORT);
417    /// assert_eq!(format!("{}", q_short_inf), String::from("0Wh"));
418    /// ```
419    pub const SHORT: i16 = qinf_base::H;
420
421    /// Infinity value of int (`0Wi`).
422    /// # Example
423    /// ```
424    /// use kdbplus::ipc::*;
425    ///
426    /// let q_int_inf = K::new_int(qinf::INT);
427    /// assert_eq!(format!("{}", q_int_inf), String::from("0Wi"));
428    /// ```
429    pub const INT: i32 = qinf_base::I;
430
431    /// Infinity value of long (`0W`).
432    /// # Example
433    /// ```
434    /// use kdbplus::ipc::*;
435    ///
436    /// let q_long = K::new_long(86400000000000);
437    /// assert_eq!(format!("{}", q_long), String::from("86400000000000"));
438    /// ```
439    pub const LONG: i64 = qinf_base::J;
440
441    /// Infinity value of real (`0We`).
442    /// # Example
443    /// ```
444    /// use kdbplus::ipc::*;
445    ///
446    /// let q_real_null = K::new_real(qnull::REAL);
447    /// assert_eq!(format!("{}", q_real_null), String::from("0Ne"));
448    /// ```
449    pub const REAL: f32 = qinf_base::E;
450
451    /// Infinity value of float (`0w`).
452    /// # Example
453    /// ```
454    /// use kdbplus::ipc::*;
455    ///
456    /// let q_float_inf = K::new_float(qinf::FLOAT);
457    /// assert_eq!(format!("{}", q_float_inf), String::from("0w"));
458    /// ```
459    pub const FLOAT: f64 = qinf_base::F;
460
461    /// Infinity value of timestamp (`0Wp`).
462    /// # Example
463    /// ```
464    /// use kdbplus::ipc::*;
465    ///
466    /// let q_timestamp_inf = K::new_timestamp(*qinf::TIMESTAMP);
467    /// assert_eq!(format!("{}", q_timestamp_inf), String::from("0Wp"));
468    /// ```
469    /// # Note
470    /// The range of timestamp in Rust is wider than in q.
471    pub const TIMESTAMP: Lazy<DateTime<Utc>> = Lazy::new(|| {
472        NaiveDate::from_ymd_opt(2292, 4, 10)
473            .unwrap()
474            .and_hms_nano_opt(23, 47, 16, 854775807)
475            .unwrap()
476            .and_local_timezone(Utc)
477            .unwrap()
478    });
479
480    /// Infinity value of month (`0Wm`).
481    /// # Example
482    /// ```
483    /// use kdbplus::ipc::*;
484    ///
485    /// let q_month_inf = K::new_month(*qinf::MONTH);
486    /// assert_eq!(format!("{}", q_month_inf), String::from("0Wm"));
487    /// ```
488    /// # Note
489    /// The range of month in Rust is narrower than in q.
490    pub const MONTH: Lazy<NaiveDate> = Lazy::new(|| NaiveDate::MAX - Duration::days(30));
491
492    /// Infinity valueo of date (`0Wd`).
493    /// # Example
494    /// ```
495    /// use kdbplus::ipc::*;
496    ///
497    /// let q_date_inf = K::new_date(qinf::DATE);
498    /// assert_eq!(format!("{}", q_date_inf), String::from("0Wd"));
499    /// ```
500    /// # Note
501    /// The range of date in Rust is narrower than in q.
502    pub const DATE: NaiveDate = NaiveDate::MAX;
503
504    /// Infinity value of datetime (`0Wz`).
505    /// # Example
506    /// ```
507    /// use kdbplus::ipc::*;
508    ///
509    /// let q_datetime_inf = K::new_datetime(*qinf::DATETIME);
510    /// assert_eq!(format!("{}", q_datetime_inf), String::from("0Wz"));
511    /// ```
512    /// # Note
513    /// The range of datetime in Rust is narrower than in q.
514    pub const DATETIME: Lazy<DateTime<Utc>> =
515        Lazy::new(|| DateTime::<Utc>::MAX_UTC - Duration::nanoseconds(999999));
516
517    /// Infinity value of timespan (`0Wn`).
518    /// # Example
519    /// ```
520    /// use kdbplus::ipc::*;
521    ///
522    /// let q_timespan_inf = K::new_timespan(*qinf::TIMESPAN);
523    /// assert_eq!(format!("{}", q_timespan_inf), String::from("0Wn"));
524    /// ```
525    pub const TIMESPAN: Lazy<Duration> = Lazy::new(|| Duration::nanoseconds(qinf_base::J));
526
527    /// Infinity value of minute (`0Wu`).
528    /// # Example
529    /// ```
530    /// use kdbplus::ipc::*;
531    ///
532    /// let q_minute_inf = K::new_minute(*qinf::MINUTE);
533    /// assert_eq!(format!("{}", q_minute_inf), String::from("0Wu"));
534    /// ```
535    pub const MINUTE: Lazy<Duration> = Lazy::new(|| Duration::minutes(qinf_base::I as i64));
536
537    /// Infinity value of second (`0Wv`).
538    /// # Example
539    /// ```
540    /// use kdbplus::ipc::*;
541    ///
542    /// let q_second_inf = K::new_second(*qinf::SECOND);
543    /// assert_eq!(format!("{}", q_second_inf), String::from("0Wv"));
544    /// ```
545    pub const SECOND: Lazy<Duration> = Lazy::new(|| Duration::seconds(qinf_base::I as i64));
546
547    /// Infinity value of time (`0Wt`).
548    /// # Example
549    /// ```
550    /// use kdbplus::ipc::*;
551    ///
552    /// let q_time_inf = K::new_time(*qinf::TIME);
553    /// assert_eq!(format!("{}", q_time_inf), String::from("0Wt"));
554    /// ```
555    pub const TIME: Lazy<Duration> = Lazy::new(|| Duration::milliseconds(qinf_base::I as i64));
556}
557
558pub mod qninf {
559    //! This module provides a list of q negative infinite values set on Rust process and used for IPC.
560    //!  The motivation to contain them in a module is to tie them up as related items rather than
561    //!  scattered values. Hence user should use these indicators with `qnull::` prefix, e.g., `qnull::FLOAT`.
562
563    use super::qninf_base;
564    use chrono::prelude::*;
565    use chrono::Duration;
566    use once_cell::sync::Lazy;
567
568    /// Infinity value of short (`-0Wh`).
569    /// # Example
570    /// ```
571    /// use kdbplus::ipc::*;
572    ///
573    /// let q_short_ninf = K::new_short(qninf::SHORT);
574    /// assert_eq!(format!("{}", q_short_ninf), String::from("-0Wh"));
575    /// ```
576    pub const SHORT: i16 = qninf_base::H;
577
578    /// Infinity value of int (`-0Wi`).
579    /// # Example
580    /// ```
581    /// use kdbplus::ipc::*;
582    ///
583    /// let q_int_ninf = K::new_int(qninf::INT);
584    /// assert_eq!(format!("{}", q_int_ninf), String::from("-0Wi"));
585    /// ```
586    pub const INT: i32 = qninf_base::I;
587
588    /// Infinity value of long (-`0W`).
589    /// # Example
590    /// ```
591    /// use kdbplus::ipc::*;
592    ///
593    /// let q_long_ninf = K::new_long(qninf::LONG);
594    /// assert_eq!(format!("{}", q_long_ninf), String::from("-0W"));
595    /// ```
596    pub const LONG: i64 = qninf_base::J;
597
598    /// Infinity value of real (`-0We`).
599    /// # Example
600    /// ```
601    /// use kdbplus::ipc::*;
602    ///
603    /// let q_real_ninf: K = K::new_real(qninf::REAL);
604    /// assert_eq!(format!("{}", q_real_ninf), String::from("-0We"));
605    /// ```
606    pub const REAL: f32 = qninf_base::E;
607
608    /// Infinity value of float (`-0w`).
609    /// # Example
610    /// ```
611    /// use kdbplus::ipc::*;
612    ///
613    /// let q_float_ninf = K::new_float(qninf::FLOAT);
614    /// assert_eq!(format!("{}", q_float_ninf), String::from("-0w"));
615    /// ```
616    pub const FLOAT: f64 = qninf_base::F;
617
618    /// Infinity value of timestamp (`-0Wp`).
619    /// # Example
620    /// ```
621    /// use kdbplus::ipc::*;
622    ///
623    /// let q_timestamp_ninf = K::new_timestamp(*qninf::TIMESTAMP);
624    /// assert_eq!(format!("{}", q_timestamp_ninf), String::from("-0Wp"));
625    /// ```
626    /// # Note
627    /// The range of timestamp in Rust is wider than in q.
628    pub const TIMESTAMP: Lazy<DateTime<Utc>> = Lazy::new(|| {
629        NaiveDate::from_ymd_opt(1707, 9, 22)
630            .unwrap()
631            .and_hms_nano_opt(0, 12, 43, 145224193)
632            .unwrap()
633            .and_local_timezone(Utc)
634            .unwrap()
635    });
636
637    /// Infinity value of month (`-0Wm`).
638    /// # Example
639    /// ```
640    /// use kdbplus::ipc::*;
641    ///
642    /// let q_month_ninf = K::new_month(*qninf::MONTH);
643    /// assert_eq!(format!("{}", q_month_ninf), String::from("-0Wm"));
644    /// ```
645    /// # Note
646    /// The range of month in Rust is narrower than in q.
647    pub const MONTH: Lazy<NaiveDate> = Lazy::new(|| NaiveDate::MIN + Duration::days(31));
648
649    /// Infinity valueo of date (`-0Wd`).
650    /// # Example
651    /// ```
652    /// use kdbplus::ipc::*;
653    ///
654    /// let q_date_ninf = K::new_date(*qninf::DATE);
655    /// assert_eq!(format!("{}", q_date_ninf), String::from("-0Wd"));
656    /// ```
657    /// # Note
658    /// The range of date in Rust is narrower than in q.
659    pub const DATE: Lazy<NaiveDate> = Lazy::new(|| NaiveDate::MIN + Duration::days(1));
660
661    /// Infinity value of datetime (`-0Wz`).
662    /// # Example
663    /// ```
664    /// use kdbplus::ipc::*;
665    ///
666    /// let q_datetime_ninf = K::new_datetime(*qninf::DATETIME);
667    /// assert_eq!(format!("{}", q_datetime_ninf), String::from("-0Wz"));
668    /// ```
669    /// # Note
670    /// The range of datetime in Rust is narrower than in q.
671    pub const DATETIME: Lazy<DateTime<Utc>> =
672        Lazy::new(|| DateTime::<Utc>::MIN_UTC + Duration::nanoseconds(1000000));
673
674    /// Infinity value of timespan (`-0Wn`).
675    /// # Example
676    /// ```
677    /// use kdbplus::ipc::*;
678    ///
679    /// let q_timespan_ninf = K::new_timespan(*qninf::TIMESPAN);
680    /// assert_eq!(format!("{}", q_timespan_ninf), String::from("-0Wn"));
681    /// ```
682    pub const TIMESPAN: Lazy<Duration> = Lazy::new(|| Duration::nanoseconds(qninf_base::J));
683
684    /// Infinity value of minute (`-0Wu`).
685    /// # Example
686    /// ```
687    /// use kdbplus::ipc::*;
688    ///
689    /// let q_minute_ninf = K::new_minute(*qninf::MINUTE);
690    /// assert_eq!(format!("{}", q_minute_ninf), String::from("-0Wu"));
691    /// ```
692    pub const MINUTE: Lazy<Duration> = Lazy::new(|| Duration::minutes(qninf_base::I as i64));
693
694    /// Infinity value of second (`-0Wv`).
695    /// # Example
696    /// ```
697    /// use kdbplus::ipc::*;
698    ///
699    /// let q_second_ninf = K::new_second(*qninf::SECOND);
700    /// assert_eq!(format!("{}", q_second_ninf), String::from("-0Wv"));
701    /// ```
702    pub const SECOND: Lazy<Duration> = Lazy::new(|| Duration::seconds(qninf_base::I as i64));
703
704    /// Infinity value of time (`-0Wt`).
705    /// # Example
706    /// ```
707    /// use kdbplus::ipc::*;
708    ///
709    /// let q_time_ninf = K::new_time(*qninf::TIME);
710    /// assert_eq!(format!("{}", q_time_ninf), String::from("-0Wt"));
711    /// ```
712    pub const TIME: Lazy<Duration> = Lazy::new(|| Duration::milliseconds(qninf_base::I as i64));
713}
714
715//++++++++++++++++++++++++++++++++++++++++++++++++++//
716// >>  Structs
717//++++++++++++++++++++++++++++++++++++++++++++++++++//
718
719//%% Alias %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
720
721/// q type denoting symbol and string.
722pub type S = String;
723/// q type denoting char.
724pub type C = i8;
725/// q type denoting bool and byte.
726pub type G = u8;
727/// q type denoting short.
728pub type H = i16;
729/// q type denoting int and its compatible types (month, date, minute, second and time) of q.
730pub type I = i32;
731/// q type denoting long and its compatible types (timestamp and timespan) of q.
732pub type J = i64;
733/// q type denoting real.
734pub type E = f32;
735/// q type denoting float and datetime.
736pub type F = f64;
737/// q type denoting GUID.
738pub type U = [G; 16];
739
740//%% AsAny %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
741
742/// Feature of q list object to be cast to concrete type internally.
743pub(crate) trait AsAny {
744    /// Return as Any type.
745    fn as_any(&self) -> &dyn Any;
746    /// Return as mutable Any type.
747    fn as_any_mut(&mut self) -> &mut dyn Any;
748}
749
750//%% Klone %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
751
752/// Trait to clone `k0_list`.
753pub(crate) trait Klone {
754    fn clone_box(&self) -> Box<dyn k0_list_inner>;
755}
756
757//%% k0_list_inner %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
758
759/// Feature of q list.
760pub(crate) trait k0_list_inner: Klone + fmt::Debug + AsAny + Send + Sync + 'static {
761    /// Get a length of inner vector.
762    fn len(&self) -> usize;
763}
764
765//%% k0_list %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
766
767/// Underlying list value of q object.
768/// # Note
769/// Usually this struct does not need to be accessed this struct directly unless user wants to
770///  access via a raw pointer for non-trivial stuff.
771#[derive(Debug)]
772pub(crate) struct k0_list {
773    /// Length of the list.
774    n: J,
775    /// Pointer referring to the head of the list. This pointer will be interpreted
776    ///  as various types when accessing `K` object to edit the list with
777    ///  [`as_mut_slice`](trait.KUtility.html#tymethod.as_mut_slice).
778    G0: Box<dyn k0_list_inner>,
779}
780
781//%% k0_inner %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
782
783/// Underlying atom value of q object.
784/// # Note
785/// Usually this struct does not need to be accessed directly unless user wants to
786///  access via a raw pointer for non-trivial stuff.
787#[derive(Clone, Debug)]
788pub(crate) enum k0_inner {
789    /// Byte type holder.
790    byte(G),
791    /// GUID type holder.
792    guid(U),
793    /// Short type holder.
794    short(H),
795    /// Int type holder.
796    int(I),
797    /// Long type older.
798    long(J),
799    /// Real type holder.
800    real(E),
801    /// Float type holder.
802    float(F),
803    /// Symbol type holder.
804    /// # Note
805    /// String type is also stored here.
806    symbol(S),
807    /// Table type holder.
808    table(K),
809    /// List type holder.
810    list(k0_list),
811    /// Null type holder.
812    null(()),
813}
814
815//%% k0 %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
816
817/// Underlying struct of q object.
818#[derive(Clone, Debug)]
819pub(crate) struct k0 {
820    /// Type indicator.
821    qtype: i8,
822    /// Attribute of list.
823    attribute: i8,
824    /// Underlying value.
825    value: k0_inner,
826}
827
828//%% K %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
829
830/// Struct representing q object.
831#[derive(Clone, Debug)]
832pub struct K(pub(crate) Box<k0>);
833
834//++++++++++++++++++++++++++++++++++++++++++++++++++//
835// >> Implementation
836//++++++++++++++++++++++++++++++++++++++++++++++++++//
837
838//%% AsAny %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
839
840impl AsAny for Vec<G> {
841    fn as_any(&self) -> &dyn Any {
842        self
843    }
844    fn as_any_mut(&mut self) -> &mut dyn Any {
845        self
846    }
847}
848
849impl AsAny for Vec<U> {
850    fn as_any(&self) -> &dyn Any {
851        self
852    }
853    fn as_any_mut(&mut self) -> &mut dyn Any {
854        self
855    }
856}
857
858impl AsAny for Vec<H> {
859    fn as_any(&self) -> &dyn Any {
860        self
861    }
862    fn as_any_mut(&mut self) -> &mut dyn Any {
863        self
864    }
865}
866
867impl AsAny for Vec<I> {
868    fn as_any(&self) -> &dyn Any {
869        self
870    }
871    fn as_any_mut(&mut self) -> &mut dyn Any {
872        self
873    }
874}
875
876impl AsAny for Vec<J> {
877    fn as_any(&self) -> &dyn Any {
878        self
879    }
880    fn as_any_mut(&mut self) -> &mut dyn Any {
881        self
882    }
883}
884
885impl AsAny for Vec<E> {
886    fn as_any(&self) -> &dyn Any {
887        self
888    }
889    fn as_any_mut(&mut self) -> &mut dyn Any {
890        self
891    }
892}
893
894impl AsAny for Vec<F> {
895    fn as_any(&self) -> &dyn Any {
896        self
897    }
898    fn as_any_mut(&mut self) -> &mut dyn Any {
899        self
900    }
901}
902
903impl AsAny for String {
904    fn as_any(&self) -> &dyn Any {
905        self
906    }
907    fn as_any_mut(&mut self) -> &mut dyn Any {
908        self
909    }
910}
911
912impl AsAny for Vec<S> {
913    fn as_any(&self) -> &dyn Any {
914        self
915    }
916    fn as_any_mut(&mut self) -> &mut dyn Any {
917        self
918    }
919}
920
921impl AsAny for Vec<K> {
922    fn as_any(&self) -> &dyn Any {
923        self
924    }
925    fn as_any_mut(&mut self) -> &mut dyn Any {
926        self
927    }
928}
929
930//%% Klone %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
931
932impl<T> Klone for T
933where
934    T: k0_list_inner + Clone,
935{
936    fn clone_box(&self) -> Box<dyn k0_list_inner> {
937        Box::new(self.clone())
938    }
939}
940
941//%% k0_list_inner %%vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
942
943impl k0_list_inner for Vec<G> {
944    fn len(&self) -> usize {
945        self.len()
946    }
947}
948
949impl k0_list_inner for Vec<U> {
950    fn len(&self) -> usize {
951        self.len()
952    }
953}
954
955impl k0_list_inner for Vec<H> {
956    fn len(&self) -> usize {
957        self.len()
958    }
959}
960
961impl k0_list_inner for Vec<I> {
962    fn len(&self) -> usize {
963        self.len()
964    }
965}
966
967impl k0_list_inner for Vec<J> {
968    fn len(&self) -> usize {
969        self.len()
970    }
971}
972
973impl k0_list_inner for Vec<E> {
974    fn len(&self) -> usize {
975        self.len()
976    }
977}
978
979impl k0_list_inner for Vec<F> {
980    fn len(&self) -> usize {
981        self.len()
982    }
983}
984
985impl k0_list_inner for String {
986    fn len(&self) -> usize {
987        self.len()
988    }
989}
990
991impl k0_list_inner for Vec<S> {
992    fn len(&self) -> usize {
993        self.len()
994    }
995}
996
997impl k0_list_inner for Vec<K> {
998    fn len(&self) -> usize {
999        self.len()
1000    }
1001}
1002
1003//%% k0_list %%vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1004
1005impl k0_list {
1006    pub(crate) fn new<T>(array: T) -> Self
1007    where
1008        T: k0_list_inner,
1009    {
1010        k0_list {
1011            n: array.len() as J,
1012            G0: Box::new(array),
1013        }
1014    }
1015}
1016
1017impl Clone for k0_list {
1018    fn clone(&self) -> Self {
1019        // Deref happens here
1020        k0_list {
1021            n: self.n,
1022            G0: self.G0.clone_box(),
1023        }
1024    }
1025}
1026
1027//%% K %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1028
1029impl K {
1030    // Constructor //----------------------------/
1031
1032    /// Base constructor of `K`.
1033    pub(crate) fn new(qtype: i8, attribute: i8, inner: k0_inner) -> Self {
1034        K(Box::new(k0 {
1035            qtype,
1036            attribute,
1037            value: inner,
1038        }))
1039    }
1040
1041    /// Construct q bool from `bool`.
1042    /// # Example
1043    /// ```
1044    /// use kdbplus::ipc::*;
1045    ///
1046    /// let q_bool_false = K::new_bool(false);
1047    /// assert_eq!(format!("{}", q_bool_false), String::from("0b"));
1048    /// ```
1049    pub fn new_bool(boolean: bool) -> Self {
1050        K::new(
1051            qtype::BOOL_ATOM,
1052            qattribute::NONE,
1053            k0_inner::byte(boolean as u8),
1054        )
1055    }
1056
1057    /// Construct q GUID from `[u8; 16]`.
1058    /// # Example
1059    /// ```
1060    /// use kdbplus::ipc::*;
1061    ///
1062    /// let q_guid = K::new_guid([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1063    /// assert_eq!(
1064    ///     format!("{}", q_guid),
1065    ///     String::from("01020304-0506-0708-090a-0b0c0d0e0f10")
1066    /// );
1067    /// ```
1068    pub fn new_guid(guid: [G; 16]) -> Self {
1069        K::new(qtype::GUID_ATOM, qattribute::NONE, k0_inner::guid(guid))
1070    }
1071
1072    /// Construct q byte from `u8`.
1073    /// # Example
1074    /// ```
1075    /// use kdbplus::ipc::*;
1076    ///
1077    /// let q_byte = K::new_byte(0x9e);
1078    /// assert_eq!(format!("{}", q_byte), String::from("0x9e"));
1079    /// ```
1080    pub fn new_byte(byte: u8) -> Self {
1081        K::new(qtype::BYTE_ATOM, qattribute::NONE, k0_inner::byte(byte))
1082    }
1083
1084    /// Construct q short from `i16`.
1085    /// # Example
1086    /// ```
1087    /// use kdbplus::ipc::*;
1088    ///
1089    /// let q_short = K::new_short(17);
1090    /// assert_eq!(format!("{}", q_short), String::from("17h"));
1091    /// ```
1092    pub fn new_short(short: i16) -> Self {
1093        K::new(qtype::SHORT_ATOM, qattribute::NONE, k0_inner::short(short))
1094    }
1095
1096    /// Construct q int from `i32`.
1097    /// # Example
1098    /// ```
1099    /// use kdbplus::ipc::*;
1100    ///
1101    /// let q_int = K::new_int(-256);
1102    /// assert_eq!(format!("{}", q_int), String::from("-256i"));
1103    /// ```
1104    pub fn new_int(int: i32) -> Self {
1105        K::new(qtype::INT_ATOM, qattribute::NONE, k0_inner::int(int))
1106    }
1107
1108    /// Construct q long from `i64`.
1109    /// # Example
1110    /// ```
1111    /// use kdbplus::ipc::*;
1112    ///
1113    /// let q_long = K::new_long(86400000000000);
1114    /// assert_eq!(format!("{}", q_long), String::from("86400000000000"));
1115    /// ```
1116    pub fn new_long(long: i64) -> Self {
1117        K::new(qtype::LONG_ATOM, qattribute::NONE, k0_inner::long(long))
1118    }
1119
1120    /// Construct q real from `f32`.
1121    /// # Example
1122    /// ```
1123    /// use kdbplus::ipc::*;
1124    ///
1125    /// let q_real = K::new_real(0.25);
1126    /// assert_eq!(format!("{:.2}", q_real), String::from("0.25e"));
1127    /// ```
1128    pub fn new_real(real: f32) -> Self {
1129        K::new(qtype::REAL_ATOM, qattribute::NONE, k0_inner::real(real))
1130    }
1131
1132    /// Construct q float from `f64`.
1133    /// # Example
1134    /// ```
1135    /// use kdbplus::ipc::*;
1136    ///
1137    /// let q_float = K::new_float(113.0456);
1138    /// assert_eq!(format!("{:.7}", q_float), String::from("113.0456000"));
1139    /// ```
1140    pub fn new_float(float: f64) -> Self {
1141        K::new(qtype::FLOAT_ATOM, qattribute::NONE, k0_inner::float(float))
1142    }
1143
1144    /// Construct q char from `char`.
1145    /// # Example
1146    /// ```
1147    /// use kdbplus::ipc::*;
1148    ///
1149    /// let q_char = K::new_char('r');
1150    /// assert_eq!(format!("{}", q_char), String::from("\"r\""));
1151    /// ```
1152    pub fn new_char(character: char) -> Self {
1153        K::new(
1154            qtype::CHAR,
1155            qattribute::NONE,
1156            k0_inner::byte(character as G),
1157        )
1158    }
1159
1160    /// Construct q symbol from `String`.
1161    /// # Example
1162    /// ```
1163    /// use kdbplus::ipc::*;
1164    ///
1165    /// let q_symbol = K::new_symbol(String::from("Jordan"));
1166    /// assert_eq!(format!("{}", q_symbol), String::from("`Jordan"));
1167    /// ```
1168    pub fn new_symbol(symbol: String) -> Self {
1169        K::new(
1170            qtype::SYMBOL_ATOM,
1171            qattribute::NONE,
1172            k0_inner::symbol(symbol),
1173        )
1174    }
1175
1176    /// Construct q timestamp from `DateTime<Utc>`.
1177    /// # Example
1178    /// ```
1179    /// use kdbplus::ipc::*;
1180    /// use chrono::prelude::*;
1181    ///
1182    /// let q_timestamp = K::new_timestamp(
1183    ///     NaiveDate::from_ymd_opt(2019, 5, 9)
1184    ///         .unwrap()
1185    ///         .and_hms_nano_opt(0, 39, 2, 194756)
1186    ///         .unwrap()
1187    ///         .and_local_timezone(Utc)
1188    ///         .unwrap(),
1189    /// );
1190    /// assert_eq!(
1191    ///     format!("{}", q_timestamp),
1192    ///     String::from("2019.05.09D00:39:02.000194756")
1193    /// );
1194    /// ```
1195    pub fn new_timestamp(timestamp: DateTime<Utc>) -> Self {
1196        K::new(
1197            qtype::TIMESTAMP_ATOM,
1198            qattribute::NONE,
1199            k0_inner::long(datetime_to_q_timestamp(timestamp)),
1200        )
1201    }
1202
1203    /// Construct q month from `Date<Utc>`.
1204    /// # Example
1205    /// ```
1206    /// use kdbplus::ipc::*;
1207    /// use chrono::prelude::*;
1208    ///
1209    /// let q_month = K::new_month(NaiveDate::from_ymd_opt(2019, 12, 15).unwrap());
1210    /// assert_eq!(format!("{}", q_month), String::from("2019.12m"));
1211    /// ```
1212    pub fn new_month(month: NaiveDate) -> Self {
1213        K::new(
1214            qtype::MONTH_ATOM,
1215            qattribute::NONE,
1216            k0_inner::int(date_to_q_month(month)),
1217        )
1218    }
1219
1220    /// Construct q date from `Date<Utc>`.
1221    /// # Example
1222    /// ```
1223    /// use kdbplus::ipc::*;
1224    /// use chrono::prelude::*;
1225    ///
1226    /// let q_date = K::new_date(NaiveDate::from_ymd_opt(2012, 3, 12).unwrap());
1227    /// assert_eq!(format!("{}", q_date), String::from("2012.03.12"));
1228    /// ```
1229    pub fn new_date(date: NaiveDate) -> Self {
1230        K::new(
1231            qtype::DATE_ATOM,
1232            qattribute::NONE,
1233            k0_inner::int(date_to_q_date(date)),
1234        )
1235    }
1236
1237    /// Construct q datetime from `DateTime<Utc>`.
1238    /// # Example
1239    /// ```
1240    /// use kdbplus::ipc::*;
1241    /// use chrono::prelude::*;
1242    ///
1243    /// let q_datetime = K::new_datetime(
1244    ///     NaiveDate::from_ymd_opt(2013, 1, 10)
1245    ///         .unwrap()
1246    ///         .and_hms_milli_opt(0, 9, 50, 38)
1247    ///         .unwrap()
1248    ///         .and_local_timezone(Utc)
1249    ///         .unwrap(),
1250    /// );
1251    /// assert_eq!(
1252    ///     format!("{}", q_datetime),
1253    ///     String::from("2013.01.10T00:09:50.038")
1254    /// );
1255    /// ```
1256    pub fn new_datetime(datetime: DateTime<Utc>) -> Self {
1257        K::new(
1258            qtype::DATETIME_ATOM,
1259            qattribute::NONE,
1260            k0_inner::float(datetime_to_q_datetime(datetime)),
1261        )
1262    }
1263
1264    /// Construct q timespan from `Duration`.
1265    /// # Example
1266    /// ```
1267    /// use kdbplus::ipc::*;
1268    /// use chrono::Duration;
1269    ///
1270    /// let q_timespan = K::new_timespan(Duration::nanoseconds(102899277539844));
1271    /// assert_eq!(
1272    ///     format!("{}", q_timespan),
1273    ///     String::from("1D04:34:59.277539844")
1274    /// );
1275    /// ```
1276    pub fn new_timespan(duration: Duration) -> Self {
1277        K::new(
1278            qtype::TIMESPAN_ATOM,
1279            qattribute::NONE,
1280            k0_inner::long(duration.num_nanoseconds().expect("duration overflow")),
1281        )
1282    }
1283
1284    /// Construct q minute from `Duration`.
1285    /// # Example
1286    /// ```
1287    /// use kdbplus::ipc::*;
1288    /// use chrono::Duration;
1289    ///
1290    /// let q_minute = K::new_minute(Duration::minutes(99));
1291    /// assert_eq!(format!("{}", q_minute), String::from("01:39"));
1292    /// ```
1293    pub fn new_minute(minute: Duration) -> Self {
1294        K::new(
1295            qtype::MINUTE_ATOM,
1296            qattribute::NONE,
1297            k0_inner::int(minute.num_minutes() as i32),
1298        )
1299    }
1300
1301    /// Construct q second from `Duration`.
1302    /// # Example
1303    /// ```
1304    /// use kdbplus::ipc::*;
1305    /// use chrono::Duration;
1306    ///
1307    /// let q_second = K::new_second(Duration::seconds(3702));
1308    /// assert_eq!(format!("{}", q_second), String::from("01:01:42"));
1309    /// ```
1310    pub fn new_second(second: Duration) -> Self {
1311        K::new(
1312            qtype::SECOND_ATOM,
1313            qattribute::NONE,
1314            k0_inner::int(second.num_seconds() as i32),
1315        )
1316    }
1317
1318    /// Construct q time from `Duration`.
1319    /// # Example
1320    /// ```
1321    /// use kdbplus::ipc::*;
1322    /// use chrono::Duration;
1323    ///
1324    /// let q_time = K::new_time(Duration::milliseconds(27843489));
1325    /// assert_eq!(format!("{}", q_time), String::from("07:44:03.489"));
1326    /// ```
1327    pub fn new_time(time: Duration) -> Self {
1328        K::new(
1329            qtype::TIME_ATOM,
1330            qattribute::NONE,
1331            k0_inner::int(time.num_milliseconds() as i32),
1332        )
1333    }
1334
1335    /// Construct q bool list from `Vec<bool>`.
1336    /// # Example
1337    /// ```
1338    /// use kdbplus::qattribute;
1339    /// use kdbplus::ipc::*;
1340    ///
1341    /// let q_bool_list = K::new_bool_list(vec![true, false, true], qattribute::NONE);
1342    /// assert_eq!(format!("{}", q_bool_list), String::from("101b"));
1343    /// ```
1344    pub fn new_bool_list(list: Vec<bool>, attribute: i8) -> Self {
1345        let array = list
1346            .into_iter()
1347            .map(|element| match element {
1348                true => 1,
1349                false => 0,
1350            })
1351            .collect::<Vec<G>>();
1352
1353        K::new(
1354            qtype::BOOL_LIST,
1355            attribute,
1356            k0_inner::list(k0_list::new(array)),
1357        )
1358    }
1359
1360    /// Construct q GUID list from `Vec<U>`.
1361    /// # Example
1362    /// ```
1363    /// use kdbplus::qattribute;
1364    /// use kdbplus::ipc::*;
1365    ///
1366    /// let q_guid_list = K::new_guid_list(
1367    ///     vec![
1368    ///         [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
1369    ///         [
1370    ///             240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
1371    ///         ],
1372    ///     ],
1373    ///     qattribute::NONE,
1374    /// );
1375    /// assert_eq!(
1376    ///     format!("{}", q_guid_list),
1377    ///     String::from(
1378    ///         "00010203-0405-0607-0809-0a0b0c0d0e0f f0f1f2f3-f4f5-f6f7-f8f9-fafbfcfdfeff"
1379    ///     )
1380    /// );
1381    /// ```
1382    pub fn new_guid_list(list: Vec<[u8; 16]>, attribute: i8) -> Self {
1383        K::new(
1384            qtype::GUID_LIST,
1385            attribute,
1386            k0_inner::list(k0_list::new(list)),
1387        )
1388    }
1389
1390    /// Construct q byte list from `Vec<G>`.
1391    /// # Example
1392    /// ```
1393    /// use kdbplus::qattribute;
1394    /// use kdbplus::ipc::*;
1395    ///
1396    /// let q_byte_list = K::new_byte_list(vec![7, 12, 21, 144], qattribute::NONE);
1397    /// assert_eq!(format!("{}", q_byte_list), String::from("0x070c1590"));
1398    /// ```
1399    pub fn new_byte_list(list: Vec<u8>, attribute: i8) -> Self {
1400        K::new(
1401            qtype::BYTE_LIST,
1402            attribute,
1403            k0_inner::list(k0_list::new(list)),
1404        )
1405    }
1406
1407    /// Construct q short list from `Vec<H>`.
1408    /// # Example
1409    /// ```
1410    /// use kdbplus::qattribute;
1411    /// use kdbplus::ipc::*;
1412    ///
1413    /// let q_short_list =
1414    ///     K::new_short_list(vec![qnull::SHORT, -7, 12, 21, 144], qattribute::SORTED);
1415    /// assert_eq!(
1416    ///     format!("{}", q_short_list),
1417    ///     String::from("`s#0N -7 12 21 144h")
1418    /// );
1419    /// ```
1420    pub fn new_short_list(list: Vec<i16>, attribute: i8) -> Self {
1421        K::new(
1422            qtype::SHORT_LIST,
1423            attribute,
1424            k0_inner::list(k0_list::new(list)),
1425        )
1426    }
1427
1428    /// Construct q int list from `Vec<I>`.
1429    /// # Example
1430    /// ```
1431    /// use kdbplus::qattribute;
1432    /// use kdbplus::ipc::*;
1433    ///
1434    /// let q_int_list = K::new_int_list(
1435    ///     vec![-10000, -10000, 21, 21, qinf::INT, 144000],
1436    ///     qattribute::PARTED,
1437    /// );
1438    /// assert_eq!(
1439    ///     format!("{}", q_int_list),
1440    ///     String::from("`p#-10000 -10000 21 21 0W 144000i")
1441    /// );
1442    /// ```
1443    pub fn new_int_list(list: Vec<i32>, attribute: i8) -> Self {
1444        K::new(
1445            qtype::INT_LIST,
1446            attribute,
1447            k0_inner::list(k0_list::new(list)),
1448        )
1449    }
1450
1451    /// Construct q long list from `Vec<J>`.
1452    /// # Example
1453    /// ```
1454    /// use kdbplus::qattribute;
1455    /// use kdbplus::ipc::*;
1456    ///
1457    /// let q_long_list = K::new_long_list(vec![-86400000000000], qattribute::UNIQUE);
1458    /// assert_eq!(
1459    ///     format!("{}", q_long_list),
1460    ///     String::from("`u#,-86400000000000")
1461    /// );
1462    /// ```
1463    pub fn new_long_list(list: Vec<i64>, attribute: i8) -> Self {
1464        K::new(
1465            qtype::LONG_LIST,
1466            attribute,
1467            k0_inner::list(k0_list::new(list)),
1468        )
1469    }
1470
1471    /// Construct q real list from `Vec<E>`.
1472    /// # Example
1473    /// ```
1474    /// use kdbplus::qattribute;
1475    /// use kdbplus::ipc::*;
1476    ///
1477    /// let q_real_list = K::new_real_list(vec![30.2, 5.002], qattribute::NONE);
1478    /// assert_eq!(format!("{:.3}", q_real_list), String::from("30.200 5.002e"));
1479    /// ```
1480    pub fn new_real_list(list: Vec<f32>, attribute: i8) -> Self {
1481        K::new(
1482            qtype::REAL_LIST,
1483            attribute,
1484            k0_inner::list(k0_list::new(list)),
1485        )
1486    }
1487
1488    /// Construct q float list from `Vec<F>`.
1489    /// # Example
1490    /// ```
1491    /// use kdbplus::qattribute;
1492    /// use kdbplus::ipc::*;
1493    ///
1494    /// let q_float_list = K::new_float_list(
1495    ///     vec![100.23, 0.4268, qnull::FLOAT, 15.882, qninf::FLOAT],
1496    ///     qattribute::NONE,
1497    /// );
1498    /// assert_eq!(
1499    ///     format!("{}", q_float_list),
1500    ///     String::from("100.23 0.4268 0n 15.882 -0w")
1501    /// );
1502    /// ```
1503    pub fn new_float_list(list: Vec<f64>, attribute: i8) -> Self {
1504        K::new(
1505            qtype::FLOAT_LIST,
1506            attribute,
1507            k0_inner::list(k0_list::new(list)),
1508        )
1509    }
1510
1511    /// Construct q string from `String`.
1512    /// # Example
1513    /// ```
1514    /// use kdbplus::qattribute;
1515    /// use kdbplus::ipc::*;
1516    ///
1517    /// let q_string = K::new_string(String::from("super"), qattribute::UNIQUE);
1518    /// assert_eq!(format!("{}", q_string), String::from("`u#\"super\""));
1519    /// ```
1520    /// # Note
1521    /// q string must be accessed with `as_string` or `as_mut_string`.
1522    pub fn new_string(string: String, attribute: i8) -> Self {
1523        K::new(qtype::STRING, attribute, k0_inner::symbol(string))
1524    }
1525
1526    /// Construct q symbol list from `Vec<String>`.
1527    /// # Example
1528    /// ```
1529    /// use kdbplus::qattribute;
1530    /// use kdbplus::ipc::*;
1531    ///
1532    /// let q_symbol_list = K::new_symbol_list(
1533    ///     vec![
1534    ///         String::from("a"),
1535    ///         String::from("b"),
1536    ///         String::from("a"),
1537    ///         String::from("c"),
1538    ///     ],
1539    ///     qattribute::GROUPED,
1540    /// );
1541    /// assert_eq!(format!("{}", q_symbol_list), String::from("`g#`a`b`a`c"));
1542    /// ```
1543    pub fn new_symbol_list(list: Vec<String>, attribute: i8) -> Self {
1544        K::new(
1545            qtype::SYMBOL_LIST,
1546            attribute,
1547            k0_inner::list(k0_list::new(list)),
1548        )
1549    }
1550
1551    /// Construct q timestamp list from `Vec<DateTime<Utc>>`.
1552    /// # Example
1553    /// ```
1554    /// use kdbplus::qattribute;
1555    /// use kdbplus::ipc::*;
1556    /// use chrono::prelude::*;
1557    ///
1558    /// let q_timestamp_list = K::new_timestamp_list(
1559    ///     vec![
1560    ///         *qnull::TIMESTAMP,
1561    ///         NaiveDate::from_ymd_opt(2000, 2, 6)
1562    ///             .unwrap()
1563    ///             .and_hms_nano_opt(5, 11, 28, 4032)
1564    ///             .unwrap()
1565    ///             .and_local_timezone(Utc)
1566    ///             .unwrap(),
1567    ///         *qinf::TIMESTAMP,
1568    ///     ],
1569    ///     qattribute::NONE,
1570    /// );
1571    /// assert_eq!(
1572    ///     format!("{}", q_timestamp_list),
1573    ///     String::from("0N 2000.02.06D05:11:28.000004032 0Wp")
1574    /// );
1575    /// ```
1576    pub fn new_timestamp_list(list: Vec<DateTime<Utc>>, attribute: i8) -> Self {
1577        let array = list
1578            .into_iter()
1579            .map(datetime_to_q_timestamp)
1580            .collect::<Vec<J>>();
1581        K::new(
1582            qtype::TIMESTAMP_LIST,
1583            attribute,
1584            k0_inner::list(k0_list::new(array)),
1585        )
1586    }
1587
1588    /// Construct q month list from `Vec<Date<Utc>>`.
1589    /// # Example
1590    /// ```
1591    /// use kdbplus::qattribute;
1592    /// use kdbplus::ipc::*;
1593    /// use chrono::prelude::*;
1594    ///
1595    /// let q_month_list = K::new_month_list(
1596    ///     vec![
1597    ///         NaiveDate::from_ymd_opt(2006, 3, 9).unwrap(),
1598    ///         NaiveDate::from_ymd_opt(1999, 5, 31).unwrap(),
1599    ///         qnull::MONTH,
1600    ///     ],
1601    ///     qattribute::NONE,
1602    /// );
1603    /// assert_eq!(
1604    ///     format!("{}", q_month_list),
1605    ///     String::from("2006.03 1999.05 0Nm")
1606    /// );
1607    /// ```
1608    pub fn new_month_list(list: Vec<NaiveDate>, attribute: i8) -> Self {
1609        let array = list.into_iter().map(date_to_q_month).collect::<Vec<I>>();
1610        K::new(
1611            qtype::MONTH_LIST,
1612            attribute,
1613            k0_inner::list(k0_list::new(array)),
1614        )
1615    }
1616
1617    /// Construct q date list from `Vec<Date<Utc>>`.
1618    /// # Example
1619    /// ```
1620    /// use kdbplus::qattribute;
1621    /// use kdbplus::ipc::*;
1622    /// use chrono::prelude::*;
1623    ///
1624    /// let q_date_list = K::new_date_list(
1625    ///     vec![
1626    ///         NaiveDate::from_ymd_opt(2001, 2, 18).unwrap(),
1627    ///         NaiveDate::from_ymd_opt(2019, 12, 12).unwrap(),
1628    ///         qinf::DATE,
1629    ///         NaiveDate::from_ymd_opt(2003, 10, 16).unwrap(),
1630    ///     ],
1631    ///     qattribute::NONE,
1632    /// );
1633    /// assert_eq!(
1634    ///     format!("{}", q_date_list),
1635    ///     String::from("2001.02.18 2019.12.12 0W 2003.10.16")
1636    /// );
1637    /// ```
1638    pub fn new_date_list(list: Vec<NaiveDate>, attribute: i8) -> Self {
1639        let array = list.into_iter().map(date_to_q_date).collect::<Vec<I>>();
1640        K::new(
1641            qtype::DATE_LIST,
1642            attribute,
1643            k0_inner::list(k0_list::new(array)),
1644        )
1645    }
1646
1647    /// Construct q datetime list from `Vec<DateTime<Utc>>`.
1648    /// # Example
1649    /// ```
1650    /// use kdbplus::qattribute;
1651    /// use kdbplus::ipc::*;
1652    /// use chrono::prelude::*;
1653    ///
1654    /// let q_datetime_list = K::new_datetime_list(
1655    ///     vec![
1656    ///         NaiveDate::from_ymd_opt(2002, 1, 26)
1657    ///             .unwrap()
1658    ///             .and_hms_nano_opt(9, 39, 2, 368376238)
1659    ///             .unwrap()
1660    ///             .and_local_timezone(Utc)
1661    ///             .unwrap(),
1662    ///         *qinf::DATETIME,
1663    ///     ],
1664    ///     qattribute::SORTED,
1665    /// );
1666    /// assert_eq!(
1667    ///     format!("{}", q_datetime_list),
1668    ///     String::from("`s#2002.01.26T09:39:02.368 0Wz")
1669    /// );
1670    /// ```
1671    pub fn new_datetime_list(list: Vec<DateTime<Utc>>, attribute: i8) -> Self {
1672        let array = list
1673            .into_iter()
1674            .map(datetime_to_q_datetime)
1675            .collect::<Vec<F>>();
1676        K::new(
1677            qtype::DATETIME_LIST,
1678            attribute,
1679            k0_inner::list(k0_list::new(array)),
1680        )
1681    }
1682
1683    /// Construct q timespan list from `Vec<Duration>`.
1684    /// # Example
1685    /// ```
1686    /// use kdbplus::qattribute;
1687    /// use kdbplus::ipc::*;
1688    /// use chrono::Duration;
1689    ///
1690    /// let q_timespan_list = K::new_timespan_list(
1691    ///     vec![
1692    ///         *qinf::TIMESPAN,
1693    ///         Duration::nanoseconds(7240514990625504),
1694    ///         Duration::nanoseconds(-107695363440640000),
1695    ///     ],
1696    ///     qattribute::NONE,
1697    /// );
1698    /// assert_eq!(
1699    ///     format!("{}", q_timespan_list),
1700    ///     String::from("0W 83D19:15:14.990625504 -1246D11:22:43.440640000")
1701    /// );
1702    /// ```
1703    pub fn new_timespan_list(list: Vec<Duration>, attribute: i8) -> Self {
1704        let array = list
1705            .into_iter()
1706            .map(|duration| duration.num_nanoseconds().expect("duration overflow"))
1707            .collect::<Vec<J>>();
1708        K::new(
1709            qtype::TIMESPAN_LIST,
1710            attribute,
1711            k0_inner::list(k0_list::new(array)),
1712        )
1713    }
1714
1715    /// Construct q minute list from `Vec<Duration>`.
1716    /// # Example
1717    /// ```
1718    /// use kdbplus::qattribute;
1719    /// use kdbplus::ipc::*;
1720    /// use chrono::Duration;
1721    ///
1722    /// let q_minute_list = K::new_minute_list(
1723    ///     vec![Duration::minutes(504), Duration::seconds(-100)],
1724    ///     qattribute::NONE,
1725    /// );
1726    /// assert_eq!(format!("{}", q_minute_list), String::from("08:24 -00:01"));
1727    /// ```
1728    pub fn new_minute_list(list: Vec<Duration>, attribute: i8) -> Self {
1729        let array = list
1730            .into_iter()
1731            .map(|duration| duration.num_minutes() as i32)
1732            .collect::<Vec<I>>();
1733        K::new(
1734            qtype::MINUTE_LIST,
1735            attribute,
1736            k0_inner::list(k0_list::new(array)),
1737        )
1738    }
1739
1740    /// Construct q second list from `Vec<Duration>`.
1741    /// # Example
1742    /// ```
1743    /// use kdbplus::qattribute;
1744    /// use kdbplus::ipc::*;
1745    /// use chrono::Duration;
1746    ///
1747    /// let q_second_list = K::new_second_list(
1748    ///     vec![
1749    ///         Duration::seconds(-3554),
1750    ///         *qinf::SECOND,
1751    ///         Duration::seconds(13744),
1752    ///         *qninf::SECOND,
1753    ///         *qnull::SECOND,
1754    ///     ],
1755    ///     qattribute::NONE,
1756    /// );
1757    /// assert_eq!(
1758    ///     format!("{}", q_second_list),
1759    ///     String::from("-00:59:14 0W 03:49:04 -0W 0Nv")
1760    /// );
1761    /// ```
1762    pub fn new_second_list(list: Vec<Duration>, attribute: i8) -> Self {
1763        let array = list
1764            .into_iter()
1765            .map(|duration| duration.num_seconds() as i32)
1766            .collect::<Vec<I>>();
1767        K::new(
1768            qtype::SECOND_LIST,
1769            attribute,
1770            k0_inner::list(k0_list::new(array)),
1771        )
1772    }
1773
1774    /// Construct q time list from `Vec<Duration>`.
1775    /// # Example
1776    /// ```
1777    /// use kdbplus::qattribute;
1778    /// use kdbplus::ipc::*;
1779    /// use chrono::Duration;
1780    ///
1781    /// let q_time_list = K::new_time_list(
1782    ///     vec![
1783    ///         Duration::milliseconds(642982),
1784    ///         Duration::milliseconds(789848),
1785    ///         *qninf::TIME,
1786    ///         Duration::milliseconds(58725553),
1787    ///     ],
1788    ///     qattribute::NONE,
1789    /// );
1790    /// assert_eq!(
1791    ///     format!("{}", q_time_list),
1792    ///     String::from("00:10:42.982 00:13:09.848 -0W 16:18:45.553")
1793    /// );
1794    /// ```
1795    pub fn new_time_list(list: Vec<Duration>, attribute: i8) -> Self {
1796        let array = list
1797            .into_iter()
1798            .map(|duration| duration.num_milliseconds() as i32)
1799            .collect::<Vec<I>>();
1800        K::new(
1801            qtype::TIME_LIST,
1802            attribute,
1803            k0_inner::list(k0_list::new(array)),
1804        )
1805    }
1806
1807    /// Construct q compound list from `Vec<K>`.
1808    /// # Example
1809    /// ```
1810    /// use kdbplus::qattribute;
1811    /// use kdbplus::ipc::*;
1812    /// use chrono::prelude::*;
1813    ///
1814    /// let q_compound_list = K::new_compound_list(vec![
1815    ///     K::new_symbol_list(
1816    ///         vec![
1817    ///             String::from("Ruby"),
1818    ///             String::from("Diamond"),
1819    ///             String::from("Sapphire"),
1820    ///         ],
1821    ///         qattribute::UNIQUE,
1822    ///     ),
1823    ///     K::new_timestamp(*qnull::TIMESTAMP),
1824    ///     K::new_long_list(vec![0, 1, 2, qninf::LONG], qattribute::NONE),
1825    ///     K::new_month_list(
1826    ///         vec![NaiveDate::from_ymd_opt(2004, 2, 7).unwrap()],
1827    ///         qattribute::NONE,
1828    ///     ),
1829    /// ]);
1830    /// assert_eq!(
1831    ///     format!("{}", q_compound_list),
1832    ///     String::from("(`u#`Ruby`Diamond`Sapphire;0Np;0 1 2 -0W;,2004.02m)")
1833    /// );
1834    /// ```
1835    pub fn new_compound_list(list: Vec<K>) -> Self {
1836        K::new(
1837            qtype::COMPOUND_LIST,
1838            qattribute::NONE,
1839            k0_inner::list(k0_list::new(list)),
1840        )
1841    }
1842
1843    /// Construct q dictionary from a pair of keys (`K`) and values (`K`).
1844    /// # Example
1845    /// ```
1846    /// use kdbplus::qattribute;
1847    /// use kdbplus::ipc::*;
1848    ///
1849    /// let keys = K::new_int_list(vec![20, 30, 40], qattribute::SORTED);
1850    /// let values = K::new_bool_list(vec![false, false, true], qattribute::NONE);
1851    /// let q_dictionary = K::new_dictionary(keys, values).unwrap();
1852    /// assert_eq!(
1853    ///     format!("{}", q_dictionary),
1854    ///     String::from("`s#20 30 40i!001b")
1855    /// );
1856    /// ```
1857    /// # Note
1858    /// This constructor can return an error object whose type is `qtype::ERROR`. In that case the error message can be
1859    ///  retrieved by [`get_symbol`](#fn.get_symbol).
1860    pub fn new_dictionary(keys: K, values: K) -> Result<Self> {
1861        if keys.len() != values.len() {
1862            Err(Error::length_mismatch(keys.len(), values.len()))
1863        } else {
1864            let qtype = if keys.0.attribute == qattribute::SORTED {
1865                qtype::SORTED_DICTIONARY
1866            } else {
1867                qtype::DICTIONARY
1868            };
1869            Ok(K::new(
1870                qtype,
1871                qattribute::NONE,
1872                k0_inner::list(k0_list::new(vec![keys, values])),
1873            ))
1874        }
1875    }
1876
1877    /// Construct q null.
1878    /// # Example
1879    /// ```
1880    /// use kdbplus::ipc::*;
1881    ///
1882    /// let q_null = K::new_null();
1883    /// assert_eq!(format!("{}", q_null), String::from("::"));
1884    /// ```
1885    pub fn new_null() -> Self {
1886        K::new(qtype::NULL, qattribute::NONE, k0_inner::null(()))
1887    }
1888
1889    /// Construct q error object.
1890    /// # Example
1891    /// ```
1892    /// use kdbplus::ipc::*;
1893    ///
1894    ///let q_error=K::new_error(String::from("woops"));
1895    ///assert_eq!(format!("{}", q_error), String::from("'woops"));
1896    /// ```
1897    pub fn new_error(error: String) -> Self {
1898        K::new(qtype::ERROR, qattribute::NONE, k0_inner::symbol(error))
1899    }
1900
1901    // Getter //---------------------------------/
1902
1903    /// Get underlying `bool` value.
1904    /// # Example
1905    /// ```
1906    /// use kdbplus::ipc::*;
1907    ///
1908    /// let q_bool = K::new_bool(true);
1909    /// assert_eq!(q_bool.get_bool(), Ok(true));
1910    /// ```
1911    pub fn get_bool(&self) -> Result<bool> {
1912        match self.0.qtype {
1913            qtype::BOOL_ATOM => match self.0.value {
1914                k0_inner::byte(boolean) => Ok(boolean != 0),
1915                _ => unreachable!(),
1916            },
1917            _ => Err(Error::invalid_cast(self.0.qtype, qtype::BOOL_ATOM)),
1918        }
1919    }
1920
1921    /// Get underlying `[u8; 16]` value.
1922    /// # Example
1923    /// ```
1924    /// use kdbplus::ipc::*;
1925    ///
1926    /// let q_guid = K::new_guid([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
1927    /// assert_eq!(
1928    ///     q_guid.get_guid(),
1929    ///     Ok([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
1930    /// );
1931    /// ```
1932    pub fn get_guid(&self) -> Result<[u8; 16]> {
1933        match self.0.qtype {
1934            qtype::GUID_ATOM => match self.0.value {
1935                k0_inner::guid(guid) => Ok(guid),
1936                _ => unreachable!(),
1937            },
1938            _ => Err(Error::invalid_cast(self.0.qtype, qtype::GUID_ATOM)),
1939        }
1940    }
1941
1942    /// Get underlying `u8` value. Compatible types are:
1943    /// - bool
1944    /// - byte
1945    /// - char
1946    /// # Example
1947    /// ```
1948    /// use kdbplus::ipc::*;
1949    ///
1950    /// let q_byte = K::new_byte(0x77);
1951    /// assert_eq!(q_byte.get_byte(), Ok(0x77));
1952    /// ```
1953    pub fn get_byte(&self) -> Result<u8> {
1954        match self.0.qtype {
1955            qtype::BOOL_ATOM | qtype::BYTE_ATOM | qtype::CHAR => match self.0.value {
1956                k0_inner::byte(byte) => Ok(byte),
1957                _ => unreachable!(),
1958            },
1959            _ => Err(Error::invalid_cast(self.0.qtype, qtype::BYTE_ATOM)),
1960        }
1961    }
1962
1963    /// Get underlying `i16` value.
1964    /// # Example
1965    /// ```
1966    /// use kdbplus::ipc::*;
1967    ///
1968    /// let q_short = K::new_short(-12);
1969    /// assert_eq!(q_short.get_short(), Ok(-12));
1970    /// ```
1971    pub fn get_short(&self) -> Result<i16> {
1972        match self.0.qtype {
1973            qtype::SHORT_ATOM => match self.0.value {
1974                k0_inner::short(short) => Ok(short),
1975                _ => unreachable!(),
1976            },
1977            _ => Err(Error::invalid_cast(self.0.qtype, qtype::SHORT_ATOM)),
1978        }
1979    }
1980
1981    /// Get underlying `i32` value. Compatible types are:
1982    /// - int
1983    /// - month
1984    /// - date
1985    /// - minute
1986    /// - second
1987    /// - time
1988    /// # Example
1989    /// ```
1990    /// use kdbplus::ipc::*;
1991    ///
1992    /// let q_int = K::new_int(144000);
1993    /// assert_eq!(q_int.get_int(), Ok(144000));
1994    /// ```
1995    pub fn get_int(&self) -> Result<i32> {
1996        match self.0.qtype {
1997            qtype::INT_ATOM
1998            | qtype::MONTH_ATOM
1999            | qtype::DATE_ATOM
2000            | qtype::MINUTE_ATOM
2001            | qtype::SECOND_ATOM
2002            | qtype::TIME_ATOM => match self.0.value {
2003                k0_inner::int(int) => Ok(int),
2004                _ => unreachable!(),
2005            },
2006            _ => Err(Error::invalid_cast(self.0.qtype, qtype::INT_ATOM)),
2007        }
2008    }
2009
2010    /// Get underlying `i64` value. Compatible types are:
2011    /// - long
2012    /// - timestamp
2013    /// - timespan
2014    /// # Example
2015    /// ```
2016    /// use kdbplus::ipc::*;
2017    ///
2018    /// let q_long = K::new_long(86400000000000);
2019    /// assert_eq!(q_long.get_long(), Ok(86400000000000));
2020    /// ```
2021    pub fn get_long(&self) -> Result<i64> {
2022        match self.0.qtype {
2023            qtype::LONG_ATOM | qtype::TIMESTAMP_ATOM | qtype::TIMESPAN_ATOM => match self.0.value {
2024                k0_inner::long(long) => Ok(long),
2025                _ => unreachable!(),
2026            },
2027            _ => Err(Error::invalid_cast(self.0.qtype, qtype::LONG_ATOM)),
2028        }
2029    }
2030
2031    /// Get underlying `f32` value.
2032    /// # Example
2033    /// ```
2034    /// use kdbplus::ipc::*;
2035    ///
2036    /// let q_real = K::new_real(0.25);
2037    /// assert_eq!(q_real.get_real(), Ok(0.25));
2038    /// ```
2039    pub fn get_real(&self) -> Result<f32> {
2040        match self.0.qtype {
2041            qtype::REAL_ATOM => match self.0.value {
2042                k0_inner::real(real) => Ok(real),
2043                _ => unreachable!(),
2044            },
2045            _ => Err(Error::invalid_cast(self.0.qtype, qtype::REAL_ATOM)),
2046        }
2047    }
2048
2049    /// Get underlying `i32` value. Compatible types are:
2050    /// - float
2051    /// - datetime
2052    /// # Example
2053    /// ```
2054    /// use kdbplus::ipc::*;
2055    ///
2056    /// let q_float = K::new_float(1000.23456);
2057    /// assert_eq!(q_float.get_float(), Ok(1000.23456));
2058    /// ```
2059    pub fn get_float(&self) -> Result<f64> {
2060        match self.0.qtype {
2061            qtype::FLOAT_ATOM | qtype::DATETIME_ATOM => match self.0.value {
2062                k0_inner::float(float) => Ok(float),
2063                _ => unreachable!(),
2064            },
2065            _ => Err(Error::invalid_cast(self.0.qtype, qtype::FLOAT_ATOM)),
2066        }
2067    }
2068
2069    /// Get underlying `char` value.
2070    /// # Example
2071    /// ```
2072    /// use kdbplus::ipc::*;
2073    ///
2074    /// let q_char = K::new_char('C');
2075    /// assert_eq!(q_char.get_char(), Ok('C'));
2076    /// ```
2077    pub fn get_char(&self) -> Result<char> {
2078        match self.0.qtype {
2079            qtype::CHAR => match self.0.value {
2080                k0_inner::byte(ch) => Ok(ch as char),
2081                _ => unreachable!(),
2082            },
2083            _ => Err(Error::invalid_cast(self.0.qtype, qtype::CHAR)),
2084        }
2085    }
2086
2087    /// Get underlying `i32` value.
2088    /// # Example
2089    /// ```
2090    /// use kdbplus::ipc::*;
2091    ///
2092    /// let q_symbol = K::new_symbol(String::from("Rust"));
2093    /// assert_eq!(q_symbol.get_symbol(), Ok("Rust"));
2094    /// ```
2095    pub fn get_symbol(&self) -> Result<&str> {
2096        match self.0.qtype {
2097            qtype::SYMBOL_ATOM => match &self.0.value {
2098                k0_inner::symbol(symbol) => Ok(symbol),
2099                _ => unreachable!(),
2100            },
2101            _ => Err(Error::invalid_cast(self.0.qtype, qtype::SYMBOL_ATOM)),
2102        }
2103    }
2104
2105    /// Get underlying timestamp value as `DateTime<Utc>`.
2106    /// # Example
2107    /// ```
2108    /// use kdbplus::ipc::*;
2109    /// use chrono::prelude::*;
2110    ///
2111    /// let q_timestamp = K::new_timestamp(
2112    ///     NaiveDate::from_ymd_opt(2001, 9, 15)
2113    ///         .unwrap()
2114    ///         .and_hms_nano_opt(4, 2, 30, 37204)
2115    ///         .unwrap()
2116    ///         .and_local_timezone(Utc)
2117    ///         .unwrap(),
2118    /// );
2119    /// assert_eq!(
2120    ///     q_timestamp.get_timestamp(),
2121    ///     Ok(NaiveDate::from_ymd_opt(2001, 9, 15)
2122    ///         .unwrap()
2123    ///         .and_hms_nano_opt(4, 2, 30, 37204)
2124    ///         .unwrap()
2125    ///         .and_local_timezone(Utc)
2126    ///         .unwrap())
2127    /// );
2128    /// ```
2129    pub fn get_timestamp(&self) -> Result<DateTime<Utc>> {
2130        match self.0.qtype {
2131            qtype::TIMESTAMP_ATOM => match self.0.value {
2132                k0_inner::long(nanos) => Ok(q_timestamp_to_datetime(nanos)),
2133                _ => unreachable!(),
2134            },
2135            _ => Err(Error::invalid_cast(self.0.qtype, qtype::TIMESTAMP_ATOM)),
2136        }
2137    }
2138
2139    /// Get underlying month value as `Date<Utc>`.
2140    /// # Example
2141    /// ```
2142    /// use kdbplus::ipc::*;
2143    /// use chrono::prelude::*;
2144    ///
2145    /// let q_month = K::new_month(NaiveDate::from_ymd_opt(2007, 8, 30).unwrap());
2146    /// assert_eq!(
2147    ///     q_month.get_month(),
2148    ///     Ok(NaiveDate::from_ymd_opt(2007, 8, 1).unwrap())
2149    /// );
2150    /// ```
2151    pub fn get_month(&self) -> Result<NaiveDate> {
2152        match self.0.qtype {
2153            qtype::MONTH_ATOM => match self.0.value {
2154                k0_inner::int(months) => Ok(q_month_to_date(months)),
2155                _ => unreachable!(),
2156            },
2157            _ => Err(Error::invalid_cast(self.0.qtype, qtype::MONTH_ATOM)),
2158        }
2159    }
2160
2161    /// Get underlying date value as `Date<Utc>`.
2162    /// # Example
2163    /// ```
2164    /// use kdbplus::ipc::*;
2165    /// use chrono::prelude::*;
2166    ///
2167    /// let q_date = K::new_date(NaiveDate::from_ymd_opt(2000, 5, 10).unwrap());
2168    /// assert_eq!(
2169    ///     q_date.get_date(),
2170    ///     Ok(NaiveDate::from_ymd_opt(2000, 5, 10).unwrap())
2171    /// );
2172    /// ```
2173    pub fn get_date(&self) -> Result<NaiveDate> {
2174        match self.0.qtype {
2175            qtype::DATE_ATOM => match self.0.value {
2176                k0_inner::int(days) => Ok(q_date_to_date(days)?),
2177                _ => unreachable!(),
2178            },
2179            _ => Err(Error::invalid_cast(self.0.qtype, qtype::DATE_ATOM)),
2180        }
2181    }
2182
2183    /// Get underlying datetime value as `DateTime<Utc>`.
2184    /// # Example
2185    /// ```
2186    /// use kdbplus::ipc::*;
2187    /// use chrono::prelude::*;
2188    ///
2189    /// let q_datetime = K::new_datetime(
2190    ///     NaiveDate::from_ymd_opt(2011, 4, 7)
2191    ///         .unwrap()
2192    ///         .and_hms_milli_opt(19, 5, 41, 385)
2193    ///         .unwrap()
2194    ///         .and_local_timezone(Utc)
2195    ///         .unwrap(),
2196    /// );
2197    /// assert_eq!(
2198    ///     q_datetime.get_datetime(),
2199    ///     Ok(NaiveDate::from_ymd_opt(2011, 4, 7)
2200    ///         .unwrap()
2201    ///         .and_hms_milli_opt(19, 5, 41, 385)
2202    ///         .unwrap()
2203    ///         .and_local_timezone(Utc)
2204    ///         .unwrap())
2205    /// );
2206    /// ```
2207    pub fn get_datetime(&self) -> Result<DateTime<Utc>> {
2208        match self.0.qtype {
2209            qtype::DATETIME_ATOM => match self.0.value {
2210                k0_inner::float(days) => Ok(q_datetime_to_datetime(days)),
2211                _ => unreachable!(),
2212            },
2213            _ => Err(Error::invalid_cast(self.0.qtype, qtype::DATETIME_ATOM)),
2214        }
2215    }
2216
2217    /// Get underlying timespan value as `Duration`.
2218    /// # Example
2219    /// ```
2220    /// use kdbplus::ipc::*;
2221    /// use chrono::Duration;
2222    ///
2223    /// let q_timespan = K::new_timespan(Duration::nanoseconds(131400000000000));
2224    /// assert_eq!(
2225    ///     q_timespan.get_timespan(),
2226    ///     Ok(Duration::nanoseconds(131400000000000))
2227    /// );
2228    /// ```
2229    pub fn get_timespan(&self) -> Result<Duration> {
2230        match self.0.qtype {
2231            qtype::TIMESPAN_ATOM => match self.0.value {
2232                k0_inner::long(nanos) => Ok(q_timespan_to_duration(nanos)),
2233                _ => unreachable!(),
2234            },
2235            _ => Err(Error::invalid_cast(self.0.qtype, qtype::TIMESPAN_ATOM)),
2236        }
2237    }
2238
2239    /// Get underlying minute value as `Duration`.
2240    /// # Example
2241    /// ```
2242    /// use kdbplus::ipc::*;
2243    /// use chrono::Duration;
2244    ///
2245    /// let q_minute = K::new_minute(Duration::minutes(30));
2246    /// assert_eq!(q_minute.get_minute(), Ok(Duration::minutes(30)));
2247    /// ```
2248    pub fn get_minute(&self) -> Result<Duration> {
2249        match self.0.qtype {
2250            qtype::MINUTE_ATOM => match self.0.value {
2251                k0_inner::int(minutes) => Ok(q_minute_to_duration(minutes)),
2252                _ => unreachable!(),
2253            },
2254            _ => Err(Error::invalid_cast(self.0.qtype, qtype::MINUTE_ATOM)),
2255        }
2256    }
2257
2258    /// Get underlying second value as `Duration`.
2259    /// # Example
2260    /// ```
2261    /// use kdbplus::ipc::*;
2262    /// use chrono::Duration;
2263    ///
2264    /// let q_second = K::new_second(Duration::seconds(30));
2265    /// assert_eq!(q_second.get_second(), Ok(Duration::seconds(30)));
2266    /// ```
2267    pub fn get_second(&self) -> Result<Duration> {
2268        match self.0.qtype {
2269            qtype::SECOND_ATOM => match self.0.value {
2270                k0_inner::int(seconds) => Ok(q_second_to_duration(seconds)),
2271                _ => unreachable!(),
2272            },
2273            _ => Err(Error::invalid_cast(self.0.qtype, qtype::SECOND_ATOM)),
2274        }
2275    }
2276
2277    /// Get underlying time value as `Duration`.
2278    /// # Example
2279    /// ```
2280    /// use kdbplus::ipc::*;
2281    /// use chrono::Duration;
2282    ///
2283    /// let q_time = K::new_time(Duration::milliseconds(3000));
2284    /// assert_eq!(q_time.get_time(), Ok(Duration::milliseconds(3000)));
2285    /// ```
2286    pub fn get_time(&self) -> Result<Duration> {
2287        match self.0.qtype {
2288            qtype::TIME_ATOM => match self.0.value {
2289                k0_inner::int(millis) => Ok(q_time_to_duration(millis)),
2290                _ => unreachable!(),
2291            },
2292            _ => Err(Error::invalid_cast(self.0.qtype, qtype::TIME_ATOM)),
2293        }
2294    }
2295
2296    /// Get underlying immutable dictionary (flipped table) of table type as `K`.
2297    /// # Example
2298    /// ```
2299    /// use kdbplus::qattribute;
2300    /// use kdbplus::ipc::*;
2301    ///
2302    /// let headers = K::new_symbol_list(
2303    ///     vec![String::from("fruit"), String::from("price")],
2304    ///     qattribute::NONE,
2305    /// );
2306    /// let columns = K::new_compound_list(vec![
2307    ///     K::new_symbol_list(
2308    ///         vec![
2309    ///             String::from("strawberry"),
2310    ///             String::from("orange"),
2311    ///             qnull::SYMBOL,
2312    ///         ],
2313    ///         qattribute::PARTED,
2314    ///     ),
2315    ///     K::new_float_list(vec![2.5, 1.25, 117.8], qattribute::NONE),
2316    /// ]);
2317    /// let q_dictionary = K::new_dictionary(headers, columns).unwrap();
2318    /// let q_table = q_dictionary.flip().unwrap();
2319    /// assert_eq!(
2320    ///     format!("{}", q_table.get_dictionary().unwrap()),
2321    ///     String::from("`fruit`price!(`p#`strawberry`orange`;2.5 1.25 117.8)")
2322    /// );
2323    /// ```
2324    pub fn get_dictionary(&self) -> Result<&K> {
2325        match self.0.qtype {
2326            qtype::TABLE => match &self.0.value {
2327                k0_inner::table(dictionary) => Ok(dictionary),
2328                _ => unreachable!(),
2329            },
2330            _ => Err(Error::invalid_cast(self.0.qtype, qtype::TABLE)),
2331        }
2332    }
2333
2334    /// Get underlying mutable dictionary (flipped table) of table type as `K`.
2335    /// # Example
2336    /// ```
2337    /// use kdbplus::qattribute;
2338    /// use kdbplus::ipc::*;
2339    ///
2340    /// let headers = K::new_symbol_list(
2341    ///     vec![String::from("fruit"), String::from("price")],
2342    ///     qattribute::NONE,
2343    /// );
2344    /// let columns = K::new_compound_list(vec![
2345    ///     K::new_symbol_list(
2346    ///         vec![
2347    ///             String::from("strawberry"),
2348    ///             String::from("orange"),
2349    ///             qnull::SYMBOL,
2350    ///         ],
2351    ///         qattribute::PARTED,
2352    ///     ),
2353    ///     K::new_float_list(vec![2.5, 1.25, 117.8], qattribute::NONE),
2354    /// ]);
2355    /// let q_dictionary = K::new_dictionary(headers, columns).unwrap();
2356    /// let mut q_table = q_dictionary.flip().unwrap();
2357    /// let inner = q_table.get_mut_dictionary().unwrap();
2358    ///
2359    /// // modify inner dictionary
2360    /// inner.as_mut_vec::<K>().unwrap()[0]
2361    ///     .push(&String::from("color"))
2362    ///     .unwrap();
2363    /// inner.as_mut_vec::<K>().unwrap()[1]
2364    ///     .push(&K::new_string(String::from("RO"), qattribute::NONE))
2365    ///     .unwrap();
2366    ///
2367    /// assert_eq!(
2368    ///     format!("{}", q_table),
2369    ///     String::from("+`fruit`price`color!(`p#`strawberry`orange`;2.5 1.25 117.8;\"RO\")")
2370    /// );
2371    /// ```
2372    pub fn get_mut_dictionary(&mut self) -> Result<&mut K> {
2373        match self.0.qtype {
2374            qtype::TABLE => match &mut self.0.value {
2375                k0_inner::table(dictionary) => Ok(dictionary),
2376                _ => unreachable!(),
2377            },
2378            _ => Err(Error::invalid_cast(self.0.qtype, qtype::TABLE)),
2379        }
2380    }
2381
2382    /// Get underlying error value as `String`.
2383    /// # Example
2384    /// ```
2385    /// use kdbplus::ipc::*;
2386    ///
2387    /// #[tokio::main]
2388    /// async fn main() -> Result<()> {
2389    ///     let mut socket = QStream::connect(ConnectionMethod::TCP, "localhost", 5000, "kdbuser:pass")
2390    ///         .await
2391    ///         .expect("Failed to connect");
2392    ///     let result = socket.send_sync_message(&"1+`a").await?;
2393    ///     assert_eq!(result.get_error_string(), Ok("type"));
2394    ///     Ok(())
2395    /// }
2396    /// ```
2397    pub fn get_error_string(&self) -> Result<&str> {
2398        match self.0.qtype {
2399            qtype::ERROR => match &self.0.value {
2400                k0_inner::symbol(error) => Ok(error),
2401                _ => unreachable!(),
2402            },
2403            _ => Err(Error::invalid_cast(self.0.qtype, qtype::ERROR)),
2404        }
2405    }
2406
2407    /// Get underlying immutable `String` value.
2408    /// # Example
2409    /// ```
2410    /// use kdbplus::qattribute;
2411    /// use kdbplus::ipc::*;
2412    ///
2413    /// let string = K::new_string(String::from("something"), qattribute::NONE);
2414    /// assert_eq!(string.as_string().unwrap(), "something");
2415    /// ```
2416    pub fn as_string(&self) -> Result<&str> {
2417        match self.0.qtype {
2418            qtype::STRING => match &self.0.value {
2419                k0_inner::symbol(string) => Ok(string),
2420                _ => unreachable!(),
2421            },
2422            _ => Err(Error::invalid_cast(self.0.qtype, qtype::STRING)),
2423        }
2424    }
2425
2426    /// Get underlying mutable `String` value.
2427    /// # Example
2428    /// ```
2429    /// use kdbplus::qattribute;
2430    /// use kdbplus::ipc::*;
2431    ///
2432    /// let mut string = K::new_string(String::from("something"), qattribute::NONE);
2433    /// string.as_mut_string().unwrap().push('!');
2434    /// assert_eq!(format!("{}", string), String::from("\"something!\""));
2435    /// ```
2436    pub fn as_mut_string(&mut self) -> Result<&mut String> {
2437        match self.0.qtype {
2438            qtype::STRING => match &mut self.0.value {
2439                k0_inner::symbol(string) => Ok(string),
2440                _ => unreachable!(),
2441            },
2442            _ => Err(Error::invalid_cast(self.0.qtype, qtype::STRING)),
2443        }
2444    }
2445
2446    /// Get the underlying mutable vector. If the specified type is wrong, it returns an empty vector.
2447    /// # Example
2448    /// ```
2449    /// use kdbplus::qattribute;
2450    /// use kdbplus::ipc::*;
2451    /// use chrono::prelude::*;
2452    ///
2453    /// let mut timestamp_list = K::new_timestamp_list(
2454    ///     vec![
2455    ///         Utc.ymd(2018, 2, 18).and_hms_nano(4, 0, 0, 100),
2456    ///         Utc.ymd(2019, 12, 3).and_hms_nano(4, 5, 10, 3456),
2457    ///     ],
2458    ///     qattribute::NONE,
2459    /// );
2460    /// timestamp_list
2461    ///     .as_mut_vec::<J>()
2462    ///     .unwrap()
2463    ///     .push(682184439000046395);
2464    /// assert_eq!(format!("{}", timestamp_list), String::from("2018.02.18D04:00:00.000000100 2019.12.03D04:05:10.000003456 2021.08.13D15:40:39.000046395"));
2465    /// ```
2466    pub fn as_mut_vec<T>(&mut self) -> Result<&mut Vec<T>>
2467    where
2468        T: 'static,
2469    {
2470        match self.0.qtype {
2471            qtype::COMPOUND_LIST
2472            | qtype::BOOL_LIST
2473            | qtype::GUID_LIST
2474            | qtype::BYTE_LIST
2475            | qtype::SHORT_LIST
2476            | qtype::INT_LIST
2477            | qtype::LONG_LIST
2478            | qtype::REAL_LIST
2479            | qtype::FLOAT_LIST
2480            | qtype::SYMBOL_LIST
2481            | qtype::TIMESTAMP_LIST
2482            | qtype::MONTH_LIST
2483            | qtype::DATE_LIST
2484            | qtype::DATETIME_LIST
2485            | qtype::TIMESPAN_LIST
2486            | qtype::MINUTE_LIST
2487            | qtype::SECOND_LIST
2488            | qtype::TIME_LIST
2489            | qtype::DICTIONARY
2490            | qtype::SORTED_DICTIONARY => match &mut self.0.value {
2491                k0_inner::list(list) => match list.G0.as_any_mut().downcast_mut::<Vec<T>>() {
2492                    Some(vector) => Ok(vector),
2493                    _ => Err(Error::invalid_cast_list(self.0.qtype)),
2494                },
2495                _ => unreachable!(),
2496            },
2497            _ => Err(Error::invalid_cast_list(self.0.qtype)),
2498        }
2499    }
2500
2501    /// Get the underlying immutable vector. If the specified type is wrong, it returns an empty vector.
2502    /// # Example
2503    /// ```
2504    /// use kdbplus::qattribute;
2505    /// use kdbplus::ipc::*;
2506    ///
2507    ///let bool_list=K::new_bool_list(vec![true, false], qattribute::UNIQUE);
2508    ///assert_eq!(*bool_list.as_vec::<G>().unwrap(), vec![1_u8, 0]);
2509    /// ```
2510    pub fn as_vec<T>(&self) -> Result<&Vec<T>>
2511    where
2512        T: 'static,
2513    {
2514        match self.0.qtype {
2515            qtype::COMPOUND_LIST
2516            | qtype::BOOL_LIST
2517            | qtype::GUID_LIST
2518            | qtype::BYTE_LIST
2519            | qtype::SHORT_LIST
2520            | qtype::INT_LIST
2521            | qtype::LONG_LIST
2522            | qtype::REAL_LIST
2523            | qtype::FLOAT_LIST
2524            | qtype::SYMBOL_LIST
2525            | qtype::TIMESTAMP_LIST
2526            | qtype::MONTH_LIST
2527            | qtype::DATE_LIST
2528            | qtype::DATETIME_LIST
2529            | qtype::TIMESPAN_LIST
2530            | qtype::MINUTE_LIST
2531            | qtype::SECOND_LIST
2532            | qtype::TIME_LIST
2533            | qtype::DICTIONARY
2534            | qtype::SORTED_DICTIONARY => match &self.0.value {
2535                k0_inner::list(list) => match list.G0.as_any().downcast_ref::<Vec<T>>() {
2536                    Some(vector) => Ok(vector),
2537                    _ => Err(Error::invalid_cast_list(self.0.qtype)),
2538                },
2539                _ => unreachable!(),
2540            },
2541            _ => Err(Error::invalid_cast_list(self.0.qtype)),
2542        }
2543    }
2544
2545    /// Get an immutable column of a table with a specified name.
2546    /// # Example
2547    /// ```
2548    /// use kdbplus::qattribute;
2549    /// use kdbplus::ipc::*;
2550    /// use chrono::prelude::*;
2551    ///
2552    /// let header = K::new_symbol_list(
2553    ///     vec![String::from("time"), String::from("sym")],
2554    ///     qattribute::NONE,
2555    /// );
2556    /// let time_column = K::new_timestamp_list(
2557    ///     vec![
2558    ///         Utc.ymd(2019, 4, 10).and_hms_nano(3, 19, 48, 1234),
2559    ///         Utc.ymd(2019, 4, 10).and_hms_nano(3, 21, 30, 948532),
2560    ///     ],
2561    ///     qattribute::NONE,
2562    /// );
2563    /// let sym_column = K::new_symbol_list(
2564    ///     vec![String::from("eggplant"), String::from("tomato")],
2565    ///     qattribute::NONE,
2566    /// );
2567    /// let table = K::new_dictionary(header, K::new_compound_list(vec![time_column, sym_column]))
2568    ///     .unwrap()
2569    ///     .flip()
2570    ///     .unwrap();
2571    /// let syms = table.get_column("sym").unwrap();
2572    /// println!("syms: {}", syms);
2573    /// ```
2574    pub fn get_column<T>(&self, column: T) -> Result<&K>
2575    where
2576        T: ToString,
2577    {
2578        match self.0.qtype {
2579            qtype::TABLE => {
2580                let dictionary = self.get_dictionary().unwrap().as_vec::<K>().unwrap();
2581                match dictionary[0]
2582                    .as_vec::<S>()
2583                    .unwrap()
2584                    .iter()
2585                    .position(|name| *name == column.to_string())
2586                {
2587                    // It is assured that value is a compound list because this is a table
2588                    Some(index) => Ok(&dictionary[1].as_vec::<K>().unwrap()[index]),
2589                    _ => Err(Error::no_such_column(column.to_string())),
2590                }
2591            }
2592            qtype::DICTIONARY => {
2593                let key_value = self.as_vec::<K>().unwrap();
2594                if key_value[0].0.qtype == qtype::TABLE {
2595                    // Keyed table
2596                    if let Ok(found_column) = key_value[0].get_column(column.to_string()) {
2597                        // Found in key table
2598                        Ok(found_column)
2599                    } else if let Ok(found_column) = key_value[1].get_column(column.to_string()) {
2600                        // Found in value table
2601                        Ok(found_column)
2602                    } else {
2603                        Err(Error::no_such_column(column.to_string()))
2604                    }
2605                } else {
2606                    // Not a keyed table
2607                    Err(Error::invalid_operation("get_column", self.0.qtype, None))
2608                }
2609            }
2610            _ => Err(Error::invalid_operation("get_column", self.0.qtype, None)),
2611        }
2612    }
2613
2614    /// Get a mutable column of a table with a specified name.
2615    /// # Example
2616    /// ```
2617    /// use kdbplus::qattribute;
2618    /// use kdbplus::ipc::*;
2619    /// use chrono::prelude::*;
2620    ///
2621    /// let header = K::new_symbol_list(
2622    ///     vec![String::from("time"), String::from("sym")],
2623    ///     qattribute::NONE,
2624    /// );
2625    /// let time_column = K::new_timestamp_list(
2626    ///     vec![
2627    ///         Utc.ymd(2019, 4, 10).and_hms_nano(3, 19, 48, 1234),
2628    ///         Utc.ymd(2019, 4, 10).and_hms_nano(3, 21, 30, 948532),
2629    ///     ],
2630    ///     qattribute::NONE,
2631    /// );
2632    /// let sym_column = K::new_symbol_list(
2633    ///     vec![String::from("eggplant"), String::from("tomato")],
2634    ///     qattribute::NONE,
2635    /// );
2636    /// let mut table =
2637    ///     K::new_dictionary(header, K::new_compound_list(vec![time_column, sym_column]))
2638    ///         .unwrap()
2639    ///         .flip()
2640    ///         .unwrap();
2641    /// let mut syms = table.get_mut_column("sym").unwrap();
2642    /// println!("syms: {}", syms);
2643    /// let _ = std::mem::replace(
2644    ///     syms,
2645    ///     K::new_symbol_list(
2646    ///         vec![String::from("banana"), String::from("strawberry")],
2647    ///         qattribute::NONE,
2648    ///     ),
2649    /// );
2650    /// println!("table: {}", table);
2651    /// ```
2652    pub fn get_mut_column<T>(&mut self, column: T) -> Result<&mut K>
2653    where
2654        T: ToString,
2655    {
2656        match self.0.qtype {
2657            qtype::TABLE => {
2658                let dictionary = self
2659                    .get_mut_dictionary()
2660                    .unwrap()
2661                    .as_mut_vec::<K>()
2662                    .unwrap();
2663                match dictionary[0]
2664                    .as_vec::<S>()
2665                    .unwrap()
2666                    .iter()
2667                    .position(|name| *name == column.to_string())
2668                {
2669                    // It is assured that value is a compound list because this is a table
2670                    Some(index) => Ok(&mut dictionary[1].as_mut_vec::<K>().unwrap()[index]),
2671                    _ => Err(Error::no_such_column(column.to_string())),
2672                }
2673            }
2674            qtype::DICTIONARY => {
2675                let key_value = self.as_vec::<K>().unwrap();
2676                if key_value[0].0.qtype == qtype::TABLE {
2677                    // Keyed table
2678                    // Search from key table
2679                    let mut dictionary = key_value[0]
2680                        .get_dictionary()
2681                        .unwrap()
2682                        .as_vec::<K>()
2683                        .unwrap();
2684                    if let Some(index) = dictionary[0]
2685                        .as_vec::<S>()
2686                        .unwrap()
2687                        .iter()
2688                        .position(|name| *name == column.to_string())
2689                    {
2690                        // It is assured that value is a compound list because this is a table
2691                        return Ok(&mut self.as_mut_vec::<K>().unwrap()[0]
2692                            .get_mut_dictionary()
2693                            .unwrap()
2694                            .as_mut_vec::<K>()
2695                            .unwrap()[1]
2696                            .as_mut_vec::<K>()
2697                            .unwrap()[index]);
2698                    }
2699                    // Search from value table
2700                    dictionary = key_value[1]
2701                        .get_dictionary()
2702                        .unwrap()
2703                        .as_vec::<K>()
2704                        .unwrap();
2705                    if let Some(index) = dictionary[0]
2706                        .as_vec::<S>()
2707                        .unwrap()
2708                        .iter()
2709                        .position(|name| *name == column.to_string())
2710                    {
2711                        // It is assured that value is a compound list because this is a table
2712                        Ok(&mut self.as_mut_vec::<K>().unwrap()[1]
2713                            .get_mut_dictionary()
2714                            .unwrap()
2715                            .as_mut_vec::<K>()
2716                            .unwrap()[1]
2717                            .as_mut_vec::<K>()
2718                            .unwrap()[index])
2719                    } else {
2720                        Err(Error::no_such_column(column.to_string()))
2721                    }
2722                } else {
2723                    // Not a keyed table
2724                    Err(Error::invalid_operation(
2725                        "get_mut_column",
2726                        self.0.qtype,
2727                        None,
2728                    ))
2729                }
2730            }
2731            _ => Err(Error::invalid_operation(
2732                "get_mut_column",
2733                self.0.qtype,
2734                None,
2735            )),
2736        }
2737    }
2738
2739    /// Get a type of q object.
2740    /// # Example
2741    /// ```
2742    /// use kdbplus::*;
2743    /// use kdbplus::ipc::*;
2744    ///
2745    /// let q_int = K::new_int(12);
2746    /// assert_eq!(q_int.get_type(), qtype::INT_ATOM);
2747    /// ```
2748    pub fn get_type(&self) -> i8 {
2749        self.0.qtype
2750    }
2751
2752    /// Get an attribute of q object.
2753    /// # Example
2754    /// ```
2755    /// use kdbplus::qattribute;
2756    /// use kdbplus::ipc::*;
2757    /// use chrono::prelude::*;
2758    ///
2759    /// let timestamp_list = K::new_timestamp_list(
2760    ///     vec![
2761    ///         Utc.ymd(2021, 3, 9).and_hms_nano(12, 5, 40, 67824),
2762    ///         Utc.ymd(2021, 3, 13).and_hms_nano(5, 47, 2, 260484387),
2763    ///     ],
2764    ///     qattribute::SORTED,
2765    /// );
2766    /// assert_eq!(timestamp_list.get_attribute(), qattribute::SORTED);
2767    /// ```
2768    pub fn get_attribute(&self) -> i8 {
2769        self.0.attribute
2770    }
2771
2772    // Setter //---------------------------------/
2773
2774    /// Set an attribute to the underlying q object.
2775    /// # Example
2776    /// ```
2777    /// use kdbplus::qattribute;
2778    /// use kdbplus::ipc::*;
2779    /// use chrono::prelude::*;
2780    ///
2781    /// let mut timestamp_list = K::new_timestamp_list(
2782    ///     vec![Utc.ymd(2021, 3, 9).and_hms_nano(12, 5, 40, 67824)],
2783    ///     qattribute::NONE,
2784    /// );
2785    /// assert_eq!(timestamp_list.get_attribute(), qattribute::NONE);
2786    /// // Push timestamp
2787    /// timestamp_list
2788    ///     .push(&Utc.ymd(2021, 3, 13).and_hms_nano(5, 47, 2, 260484387))
2789    ///     .unwrap();
2790    /// timestamp_list.set_attribute(qattribute::SORTED);
2791    /// assert_eq!(timestamp_list.get_attribute(), qattribute::SORTED);
2792    /// ```
2793    /// # Note
2794    /// The validity of the attribute is not checked. For example, if you set a sorted attribute to
2795    ///  an unsorted list, it does not return an error. It will fail in q process.
2796    pub fn set_attribute(&mut self, attribute: i8) {
2797        self.0.attribute = attribute;
2798    }
2799
2800    // Push/Pop //-------------------------------/
2801
2802    /// Increment `n` of `k0_list`.
2803    fn increment(&mut self) {
2804        match &mut self.0.value {
2805            k0_inner::list(list) => list.n += 1,
2806            _ => unreachable!(),
2807        }
2808    }
2809
2810    /// Decrement `n` of `k0_list`.
2811    fn decrement(&mut self) {
2812        match &mut self.0.value {
2813            k0_inner::list(list) => list.n -= 1,
2814            _ => unreachable!(),
2815        }
2816    }
2817
2818    /// Add an element to the tail of the underlying list.
2819    /// # Parameters
2820    /// - `element`: An element to insert. The type needs to be a one used for atom constructor `K::new_*`. For example,
2821    ///   int element must be a `i32` type and timestamp element must be a `DateTime<Utc>` type.
2822    /// # Example
2823    /// ```
2824    /// use kdbplus::qattribute;
2825    /// use kdbplus::ipc::*;
2826    ///
2827    /// let mut symbol_list = K::new_symbol_list(vec![String::from("first")], qattribute::NONE);
2828    /// symbol_list.push(&String::from("second")).unwrap();
2829    /// if let Err(error) = symbol_list.push(&12) {
2830    ///     eprintln!("Oh no!! {}", error);
2831    /// }
2832    /// assert_eq!(
2833    ///     *symbol_list.as_vec::<S>().unwrap(),
2834    ///     vec![String::from("first"), String::from("second")]
2835    /// );
2836    ///
2837    /// let mut string_list = K::new_compound_list(vec![K::new_string(
2838    ///     String::from("string"),
2839    ///     qattribute::NONE,
2840    /// )]);
2841    /// string_list.push(&K::new_bool(false)).unwrap();
2842    /// assert_eq!(format!("{}", string_list), String::from("(\"string\";0b)"));
2843    /// ```
2844    pub fn push(&mut self, element: &dyn Any) -> Result<()> {
2845        match self.0.qtype {
2846            qtype::BOOL_LIST => {
2847                if let Some(boolean) = element.downcast_ref::<bool>() {
2848                    self.increment();
2849                    self.as_mut_vec::<G>().unwrap().push(*boolean as u8);
2850                    Ok(())
2851                } else {
2852                    Err(Error::insert_wrong_element(false, qtype::BOOL_LIST, "bool"))
2853                }
2854            }
2855            qtype::GUID_LIST => {
2856                if let Some(guid) = element.downcast_ref::<U>() {
2857                    self.increment();
2858                    self.as_mut_vec::<U>().unwrap().push(*guid);
2859                    Ok(())
2860                } else {
2861                    Err(Error::insert_wrong_element(
2862                        false,
2863                        qtype::GUID_LIST,
2864                        "[u8; 16]",
2865                    ))
2866                }
2867            }
2868            qtype::BYTE_LIST => {
2869                if let Some(byte) = element.downcast_ref::<u8>() {
2870                    self.increment();
2871                    self.as_mut_vec::<G>().unwrap().push(*byte);
2872                    Ok(())
2873                } else {
2874                    Err(Error::insert_wrong_element(false, qtype::BYTE_LIST, "u8"))
2875                }
2876            }
2877            qtype::SHORT_LIST => {
2878                if let Some(short) = element.downcast_ref::<i16>() {
2879                    self.increment();
2880                    self.as_mut_vec::<H>().unwrap().push(*short);
2881                    Ok(())
2882                } else {
2883                    Err(Error::insert_wrong_element(false, qtype::SHORT_LIST, "i16"))
2884                }
2885            }
2886            qtype::INT_LIST => {
2887                if let Some(int) = element.downcast_ref::<i32>() {
2888                    self.increment();
2889                    self.as_mut_vec::<I>().unwrap().push(*int);
2890                    Ok(())
2891                } else {
2892                    Err(Error::insert_wrong_element(
2893                        false,
2894                        qtype::INT_LIST,
2895                        "[u8; 16]",
2896                    ))
2897                }
2898            }
2899            qtype::LONG_LIST => {
2900                if let Some(long) = element.downcast_ref::<i64>() {
2901                    self.increment();
2902                    self.as_mut_vec::<J>().unwrap().push(*long);
2903                    Ok(())
2904                } else {
2905                    Err(Error::insert_wrong_element(false, qtype::LONG_LIST, "i64"))
2906                }
2907            }
2908            qtype::REAL_LIST => {
2909                if let Some(real) = element.downcast_ref::<f32>() {
2910                    self.increment();
2911                    self.as_mut_vec::<E>().unwrap().push(*real);
2912                    Ok(())
2913                } else {
2914                    Err(Error::insert_wrong_element(false, qtype::FLOAT_LIST, "f32"))
2915                }
2916            }
2917            qtype::FLOAT_LIST => {
2918                if let Some(float) = element.downcast_ref::<f64>() {
2919                    self.increment();
2920                    self.as_mut_vec::<F>().unwrap().push(*float);
2921                    Ok(())
2922                } else {
2923                    Err(Error::insert_wrong_element(false, qtype::FLOAT_LIST, "f64"))
2924                }
2925            }
2926            qtype::STRING => {
2927                if let Some(ch) = element.downcast_ref::<char>() {
2928                    self.as_mut_string().unwrap().push(*ch);
2929                    Ok(())
2930                } else {
2931                    Err(Error::insert_wrong_element(false, qtype::STRING, "char"))
2932                }
2933            }
2934            qtype::SYMBOL_LIST => {
2935                if let Some(symbol) = element.downcast_ref::<String>() {
2936                    self.increment();
2937                    self.as_mut_vec::<S>().unwrap().push(symbol.clone());
2938                    Ok(())
2939                } else {
2940                    Err(Error::insert_wrong_element(
2941                        false,
2942                        qtype::SYMBOL_LIST,
2943                        "String",
2944                    ))
2945                }
2946            }
2947            qtype::TIMESTAMP_LIST => {
2948                if let Some(timestamp) = element.downcast_ref::<DateTime<Utc>>() {
2949                    self.increment();
2950                    self.as_mut_vec::<J>()
2951                        .unwrap()
2952                        .push(datetime_to_q_timestamp(*timestamp));
2953                    Ok(())
2954                } else {
2955                    Err(Error::insert_wrong_element(
2956                        false,
2957                        qtype::TIMESTAMP_LIST,
2958                        "DateTime<Utc>",
2959                    ))
2960                }
2961            }
2962            qtype::MONTH_LIST => {
2963                if let Some(month) = element.downcast_ref::<NaiveDate>() {
2964                    self.increment();
2965                    self.as_mut_vec::<I>()
2966                        .unwrap()
2967                        .push(date_to_q_month(*month));
2968                    Ok(())
2969                } else {
2970                    Err(Error::insert_wrong_element(
2971                        false,
2972                        qtype::MONTH_LIST,
2973                        "Date<Utc>",
2974                    ))
2975                }
2976            }
2977            qtype::DATE_LIST => {
2978                if let Some(date) = element.downcast_ref::<NaiveDate>() {
2979                    self.increment();
2980                    self.as_mut_vec::<I>().unwrap().push(date_to_q_date(*date));
2981                    Ok(())
2982                } else {
2983                    Err(Error::insert_wrong_element(
2984                        false,
2985                        qtype::DATE_LIST,
2986                        "Date<Utc>",
2987                    ))
2988                }
2989            }
2990            qtype::DATETIME_LIST => {
2991                if let Some(datetime) = element.downcast_ref::<DateTime<Utc>>() {
2992                    self.increment();
2993                    self.as_mut_vec::<F>()
2994                        .unwrap()
2995                        .push(datetime_to_q_datetime(*datetime));
2996                    Ok(())
2997                } else {
2998                    Err(Error::insert_wrong_element(
2999                        false,
3000                        qtype::DATETIME_LIST,
3001                        "DateTime<Utc>",
3002                    ))
3003                }
3004            }
3005            qtype::TIMESPAN_LIST => {
3006                if let Some(timespan) = element.downcast_ref::<Duration>() {
3007                    self.increment();
3008                    self.as_mut_vec::<J>()
3009                        .unwrap()
3010                        .push(timespan.num_nanoseconds().expect("duration overflow"));
3011                    Ok(())
3012                } else {
3013                    Err(Error::insert_wrong_element(
3014                        false,
3015                        qtype::TIMESPAN_LIST,
3016                        "Duration",
3017                    ))
3018                }
3019            }
3020            qtype::MINUTE_LIST => {
3021                if let Some(minute) = element.downcast_ref::<Duration>() {
3022                    self.increment();
3023                    self.as_mut_vec::<I>()
3024                        .unwrap()
3025                        .push(minute.num_minutes() as i32);
3026                    Ok(())
3027                } else {
3028                    Err(Error::insert_wrong_element(
3029                        false,
3030                        qtype::MINUTE_LIST,
3031                        "Duration",
3032                    ))
3033                }
3034            }
3035            qtype::SECOND_LIST => {
3036                if let Some(second) = element.downcast_ref::<Duration>() {
3037                    self.increment();
3038                    self.as_mut_vec::<I>()
3039                        .unwrap()
3040                        .push(second.num_seconds() as i32);
3041                    Ok(())
3042                } else {
3043                    Err(Error::insert_wrong_element(
3044                        false,
3045                        qtype::SECOND_LIST,
3046                        "Duration",
3047                    ))
3048                }
3049            }
3050            qtype::TIME_LIST => {
3051                if let Some(time) = element.downcast_ref::<Duration>() {
3052                    self.increment();
3053                    self.as_mut_vec::<I>()
3054                        .unwrap()
3055                        .push(time.num_milliseconds() as i32);
3056                    Ok(())
3057                } else {
3058                    Err(Error::insert_wrong_element(
3059                        false,
3060                        qtype::TIME_LIST,
3061                        "Duration",
3062                    ))
3063                }
3064            }
3065            qtype::COMPOUND_LIST => {
3066                if let Some(k) = element.downcast_ref::<K>() {
3067                    self.increment();
3068                    self.as_mut_vec::<K>().unwrap().push(k.clone());
3069                    Ok(())
3070                } else {
3071                    Err(Error::insert_wrong_element(
3072                        false,
3073                        qtype::COMPOUND_LIST,
3074                        "K",
3075                    ))
3076                }
3077            }
3078            _ => Err(Error::invalid_operation("push", self.0.qtype, None)),
3079        }
3080    }
3081
3082    /// Insert an element to the underlying q list at the location specified location by an index.
3083    /// # Parameters
3084    /// - `index`: Index of the location where the new element is inserted.
3085    /// - `element`: An element to insert. The type needs to be a one used for atom constructor `K::new_*`. For example,
3086    ///   int element must be a `i32` type and timestamp element must be a `DateTime<Utc>` type.
3087    /// # Example
3088    /// ```
3089    /// use kdbplus::qattribute;
3090    /// use kdbplus::ipc::*;
3091    /// use chrono::Duration;
3092    ///
3093    /// let mut q_symbol_list = K::new_symbol_list(vec![String::from("almond")], qattribute::NONE);
3094    /// q_symbol_list.push(&String::from("hazel")).unwrap();
3095    /// q_symbol_list.insert(1, &String::from("macadamia")).unwrap();
3096    /// assert_eq!(
3097    ///     *q_symbol_list.as_vec::<S>().unwrap(),
3098    ///     vec![
3099    ///         String::from("almond"),
3100    ///         String::from("macadamia"),
3101    ///         String::from("hazel")
3102    ///     ]
3103    /// );
3104    ///
3105    /// let mut q_minute_list = K::new_minute_list(vec![Duration::minutes(1024)], qattribute::NONE);
3106    /// q_minute_list.insert(0, &Duration::minutes(12)).unwrap();
3107    /// assert_eq!(*q_minute_list.as_vec::<I>().unwrap(), vec![12, 1024]);
3108    /// ```
3109    pub fn insert(&mut self, index: usize, element: &dyn Any) -> Result<()> {
3110        if index > self.len() {
3111            Err(Error::index_out_of_bounds(self.len(), index))
3112        } else {
3113            match self.0.qtype {
3114                qtype::BOOL_LIST => {
3115                    if let Some(boolean) = element.downcast_ref::<bool>() {
3116                        self.increment();
3117                        self.as_mut_vec::<G>()
3118                            .unwrap()
3119                            .insert(index, *boolean as u8);
3120                        Ok(())
3121                    } else {
3122                        Err(Error::insert_wrong_element(true, qtype::BOOL_LIST, "bool"))
3123                    }
3124                }
3125                qtype::GUID_LIST => {
3126                    if let Some(guid) = element.downcast_ref::<U>() {
3127                        self.increment();
3128                        self.as_mut_vec::<U>().unwrap().insert(index, *guid);
3129                        Ok(())
3130                    } else {
3131                        Err(Error::insert_wrong_element(
3132                            true,
3133                            qtype::GUID_LIST,
3134                            "[u8; 16]",
3135                        ))
3136                    }
3137                }
3138                qtype::BYTE_LIST => {
3139                    if let Some(byte) = element.downcast_ref::<u8>() {
3140                        self.increment();
3141                        self.as_mut_vec::<G>().unwrap().insert(index, *byte);
3142                        Ok(())
3143                    } else {
3144                        Err(Error::insert_wrong_element(true, qtype::BYTE_LIST, "u8"))
3145                    }
3146                }
3147                qtype::SHORT_LIST => {
3148                    if let Some(short) = element.downcast_ref::<i16>() {
3149                        self.increment();
3150                        self.as_mut_vec::<H>().unwrap().insert(index, *short);
3151                        Ok(())
3152                    } else {
3153                        Err(Error::insert_wrong_element(false, qtype::SHORT_LIST, "i16"))
3154                    }
3155                }
3156                qtype::INT_LIST => {
3157                    if let Some(int) = element.downcast_ref::<i32>() {
3158                        self.increment();
3159                        self.as_mut_vec::<I>().unwrap().insert(index, *int);
3160                        Ok(())
3161                    } else {
3162                        Err(Error::insert_wrong_element(false, qtype::INT_LIST, "i32"))
3163                    }
3164                }
3165                qtype::LONG_LIST => {
3166                    if let Some(long) = element.downcast_ref::<i64>() {
3167                        self.increment();
3168                        self.as_mut_vec::<J>().unwrap().insert(index, *long);
3169                        Ok(())
3170                    } else {
3171                        Err(Error::insert_wrong_element(false, qtype::LONG_LIST, "i64"))
3172                    }
3173                }
3174                qtype::REAL_LIST => {
3175                    if let Some(real) = element.downcast_ref::<f32>() {
3176                        self.increment();
3177                        self.as_mut_vec::<E>().unwrap().insert(index, *real);
3178                        Ok(())
3179                    } else {
3180                        Err(Error::insert_wrong_element(false, qtype::REAL_LIST, "f32"))
3181                    }
3182                }
3183                qtype::FLOAT_LIST => {
3184                    if let Some(float) = element.downcast_ref::<f64>() {
3185                        self.increment();
3186                        self.as_mut_vec::<F>().unwrap().insert(index, *float);
3187                        Ok(())
3188                    } else {
3189                        Err(Error::insert_wrong_element(false, qtype::FLOAT_LIST, "f64"))
3190                    }
3191                }
3192                qtype::STRING => {
3193                    if let Some(ch) = element.downcast_ref::<char>() {
3194                        self.as_mut_string().unwrap().insert(index, *ch);
3195                        Ok(())
3196                    } else {
3197                        Err(Error::insert_wrong_element(false, qtype::STRING, "char"))
3198                    }
3199                }
3200                qtype::SYMBOL_LIST => {
3201                    if let Some(symbol) = element.downcast_ref::<String>() {
3202                        self.increment();
3203                        self.as_mut_vec::<S>()
3204                            .unwrap()
3205                            .insert(index, symbol.clone());
3206                        Ok(())
3207                    } else {
3208                        Err(Error::insert_wrong_element(
3209                            false,
3210                            qtype::SYMBOL_LIST,
3211                            "String",
3212                        ))
3213                    }
3214                }
3215                qtype::TIMESTAMP_LIST => {
3216                    if let Some(timestamp) = element.downcast_ref::<DateTime<Utc>>() {
3217                        self.increment();
3218                        self.as_mut_vec::<J>()
3219                            .unwrap()
3220                            .insert(index, datetime_to_q_timestamp(*timestamp));
3221                        Ok(())
3222                    } else {
3223                        Err(Error::insert_wrong_element(
3224                            false,
3225                            qtype::TIMESTAMP_LIST,
3226                            "DateTime<Utc>",
3227                        ))
3228                    }
3229                }
3230                qtype::MONTH_LIST => {
3231                    if let Some(month) = element.downcast_ref::<NaiveDate>() {
3232                        self.increment();
3233                        self.as_mut_vec::<I>()
3234                            .unwrap()
3235                            .insert(index, date_to_q_month(*month));
3236                        Ok(())
3237                    } else {
3238                        Err(Error::insert_wrong_element(
3239                            false,
3240                            qtype::MONTH_LIST,
3241                            "Date<Utc>",
3242                        ))
3243                    }
3244                }
3245                qtype::DATE_LIST => {
3246                    if let Some(date) = element.downcast_ref::<NaiveDate>() {
3247                        self.increment();
3248                        self.as_mut_vec::<I>()
3249                            .unwrap()
3250                            .insert(index, date_to_q_date(*date));
3251                        Ok(())
3252                    } else {
3253                        Err(Error::insert_wrong_element(
3254                            false,
3255                            qtype::DATE_LIST,
3256                            "Date<Utc>",
3257                        ))
3258                    }
3259                }
3260                qtype::DATETIME_LIST => {
3261                    if let Some(datetime) = element.downcast_ref::<DateTime<Utc>>() {
3262                        self.increment();
3263                        self.as_mut_vec::<F>()
3264                            .unwrap()
3265                            .insert(index, datetime_to_q_datetime(*datetime));
3266                        Ok(())
3267                    } else {
3268                        Err(Error::insert_wrong_element(
3269                            false,
3270                            qtype::DATETIME_LIST,
3271                            "DateTime<Utc>",
3272                        ))
3273                    }
3274                }
3275                qtype::TIMESPAN_LIST => {
3276                    if let Some(timespan) = element.downcast_ref::<Duration>() {
3277                        self.increment();
3278                        self.as_mut_vec::<J>().unwrap().insert(
3279                            index,
3280                            timespan.num_nanoseconds().expect("duration overflow"),
3281                        );
3282                        Ok(())
3283                    } else {
3284                        Err(Error::insert_wrong_element(
3285                            false,
3286                            qtype::TIMESPAN_LIST,
3287                            "Duration",
3288                        ))
3289                    }
3290                }
3291                qtype::MINUTE_LIST => {
3292                    if let Some(minute) = element.downcast_ref::<Duration>() {
3293                        self.increment();
3294                        self.as_mut_vec::<I>()
3295                            .unwrap()
3296                            .insert(index, minute.num_minutes() as i32);
3297                        Ok(())
3298                    } else {
3299                        Err(Error::insert_wrong_element(
3300                            false,
3301                            qtype::MINUTE_LIST,
3302                            "Duration",
3303                        ))
3304                    }
3305                }
3306                qtype::SECOND_LIST => {
3307                    if let Some(second) = element.downcast_ref::<Duration>() {
3308                        self.increment();
3309                        self.as_mut_vec::<I>()
3310                            .unwrap()
3311                            .insert(index, second.num_seconds() as i32);
3312                        Ok(())
3313                    } else {
3314                        Err(Error::insert_wrong_element(
3315                            false,
3316                            qtype::SECOND_LIST,
3317                            "Duration",
3318                        ))
3319                    }
3320                }
3321                qtype::TIME_LIST => {
3322                    if let Some(time) = element.downcast_ref::<Duration>() {
3323                        self.increment();
3324                        self.as_mut_vec::<I>()
3325                            .unwrap()
3326                            .insert(index, time.num_milliseconds() as i32);
3327                        Ok(())
3328                    } else {
3329                        Err(Error::insert_wrong_element(
3330                            false,
3331                            qtype::TIME_LIST,
3332                            "Duration",
3333                        ))
3334                    }
3335                }
3336                qtype::COMPOUND_LIST => {
3337                    if let Some(k) = element.downcast_ref::<K>() {
3338                        self.increment();
3339                        self.as_mut_vec::<K>().unwrap().insert(index, k.clone());
3340                        Ok(())
3341                    } else {
3342                        Err(Error::insert_wrong_element(
3343                            false,
3344                            qtype::COMPOUND_LIST,
3345                            "K",
3346                        ))
3347                    }
3348                }
3349                _ => Err(Error::invalid_operation("insert", self.0.qtype, None)),
3350            }
3351        }
3352    }
3353
3354    /// Pop a `bool` object from q bool list.
3355    /// # Example
3356    /// ```
3357    /// use kdbplus::qattribute;
3358    /// use kdbplus::ipc::*;
3359    ///
3360    /// let mut q_bool_list = K::new_bool_list(vec![false, true], qattribute::NONE);
3361    /// let tail = q_bool_list.pop_bool().unwrap();
3362    /// assert_eq!(tail, true);
3363    /// ```
3364    pub fn pop_bool(&mut self) -> Result<bool> {
3365        if self.is_empty() {
3366            // 0 length
3367            Err(Error::pop_from_empty_list())
3368        } else {
3369            match self.0.qtype {
3370                qtype::BOOL_LIST => {
3371                    self.decrement();
3372                    Ok(self.as_mut_vec::<G>().unwrap().pop().unwrap() != 0)
3373                }
3374                _ => Err(Error::invalid_operation(
3375                    "pop_bool",
3376                    self.0.qtype,
3377                    Some(qtype::BOOL_LIST),
3378                )),
3379            }
3380        }
3381    }
3382
3383    /// Pop a `[u8; 16]` object from q GUID list.
3384    /// # Example
3385    /// ```
3386    /// use kdbplus::qattribute;
3387    /// use kdbplus::ipc::*;
3388    ///
3389    /// let mut q_guid_list = K::new_guid_list(
3390    ///     vec![[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]],
3391    ///     qattribute::NONE,
3392    /// );
3393    /// let tail = q_guid_list.pop_guid().unwrap();
3394    /// assert_eq!(
3395    ///     tail,
3396    ///     [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
3397    /// );
3398    /// ```
3399    pub fn pop_guid(&mut self) -> Result<[u8; 16]> {
3400        if self.is_empty() {
3401            // 0 length
3402            Err(Error::pop_from_empty_list())
3403        } else {
3404            match self.0.qtype {
3405                qtype::GUID_LIST => {
3406                    self.decrement();
3407                    Ok(self.as_mut_vec::<U>().unwrap().pop().unwrap())
3408                }
3409                _ => Err(Error::invalid_operation(
3410                    "pop_guid",
3411                    self.0.qtype,
3412                    Some(qtype::GUID_LIST),
3413                )),
3414            }
3415        }
3416    }
3417
3418    /// Pop a `u8` object from q byte list.
3419    /// # Example
3420    /// ```
3421    /// use kdbplus::qattribute;
3422    /// use kdbplus::ipc::*;
3423    ///
3424    /// let mut q_byte_list = K::new_byte_list(vec![0x77, 0x99, 0xae], qattribute::NONE);
3425    /// let tail = q_byte_list.pop_byte().unwrap();
3426    /// assert_eq!(tail, 0xae_u8);
3427    /// ```
3428    pub fn pop_byte(&mut self) -> Result<u8> {
3429        if self.is_empty() {
3430            // 0 length
3431            Err(Error::pop_from_empty_list())
3432        } else {
3433            match self.0.qtype {
3434                qtype::BYTE_LIST => {
3435                    self.decrement();
3436                    Ok(self.as_mut_vec::<G>().unwrap().pop().unwrap())
3437                }
3438                _ => Err(Error::invalid_operation(
3439                    "pop_byte",
3440                    self.0.qtype,
3441                    Some(qtype::BYTE_LIST),
3442                )),
3443            }
3444        }
3445    }
3446
3447    /// Pop a `i16` object from q short list.
3448    /// # Example
3449    /// ```
3450    /// use kdbplus::qattribute;
3451    /// use kdbplus::ipc::*;
3452    ///
3453    /// let mut q_short_list = K::new_short_list(vec![12, 50], qattribute::NONE);
3454    /// let tail = q_short_list.pop_short().unwrap();
3455    /// assert_eq!(tail, 50_i16);
3456    /// ```
3457    pub fn pop_short(&mut self) -> Result<i16> {
3458        if self.is_empty() {
3459            // 0 length
3460            Err(Error::pop_from_empty_list())
3461        } else {
3462            match self.0.qtype {
3463                qtype::SHORT_LIST => {
3464                    self.decrement();
3465                    Ok(self.as_mut_vec::<H>().unwrap().pop().unwrap())
3466                }
3467                _ => Err(Error::invalid_operation(
3468                    "pop_short",
3469                    self.0.qtype,
3470                    Some(qtype::SHORT_LIST),
3471                )),
3472            }
3473        }
3474    }
3475
3476    /// Pop a `i32` object from q int list.
3477    /// # Example
3478    /// ```
3479    /// use kdbplus::qattribute;
3480    /// use kdbplus::ipc::*;
3481    ///
3482    /// let mut q_int_list = K::new_int_list(vec![144000, -1, 888], qattribute::NONE);
3483    /// let tail = q_int_list.pop_int().unwrap();
3484    /// assert_eq!(tail, 888);
3485    /// ```
3486    pub fn pop_int(&mut self) -> Result<i32> {
3487        if self.is_empty() {
3488            // 0 length
3489            Err(Error::pop_from_empty_list())
3490        } else {
3491            match self.0.qtype {
3492                qtype::INT_LIST => {
3493                    self.decrement();
3494                    Ok(self.as_mut_vec::<I>().unwrap().pop().unwrap())
3495                }
3496                _ => Err(Error::invalid_operation(
3497                    "pop_int",
3498                    self.0.qtype,
3499                    Some(qtype::INT_LIST),
3500                )),
3501            }
3502        }
3503    }
3504
3505    /// Pop a `i64` object from q long list.
3506    /// # Example
3507    /// ```
3508    /// use kdbplus::qattribute;
3509    /// use kdbplus::ipc::*;
3510    ///
3511    /// let mut q_long_list = K::new_long_list(vec![-86400_i64, 13800000000], qattribute::NONE);
3512    /// let tail = q_long_list.pop_long().unwrap();
3513    /// assert_eq!(tail, 13800000000_i64);
3514    /// ```
3515    pub fn pop_long(&mut self) -> Result<i64> {
3516        if self.is_empty() {
3517            // 0 length
3518            Err(Error::pop_from_empty_list())
3519        } else {
3520            match self.0.qtype {
3521                qtype::LONG_LIST => {
3522                    self.decrement();
3523                    Ok(self.as_mut_vec::<J>().unwrap().pop().unwrap())
3524                }
3525                _ => Err(Error::invalid_operation(
3526                    "pop_long",
3527                    self.0.qtype,
3528                    Some(qtype::LONG_LIST),
3529                )),
3530            }
3531        }
3532    }
3533
3534    /// Pop a `f32` object from q real list.
3535    /// # Example
3536    /// ```
3537    /// use kdbplus::qattribute;
3538    /// use kdbplus::ipc::*;
3539    ///
3540    /// let mut q_real_list = K::new_real_list(vec![9.22_f32, -0.1], qattribute::NONE);
3541    /// let tail = q_real_list.pop_real().unwrap();
3542    /// assert_eq!(tail, -0.1_f32);
3543    /// ```
3544    pub fn pop_real(&mut self) -> Result<f32> {
3545        if self.is_empty() {
3546            // 0 length
3547            Err(Error::pop_from_empty_list())
3548        } else {
3549            match self.0.qtype {
3550                qtype::REAL_LIST => {
3551                    self.decrement();
3552                    Ok(self.as_mut_vec::<E>().unwrap().pop().unwrap())
3553                }
3554                _ => Err(Error::invalid_operation(
3555                    "pop_real",
3556                    self.0.qtype,
3557                    Some(qtype::REAL_LIST),
3558                )),
3559            }
3560        }
3561    }
3562
3563    /// Pop a `f64` object from q float list.
3564    /// # Example
3565    /// ```
3566    /// use kdbplus::qattribute;
3567    /// use kdbplus::ipc::*;
3568    ///
3569    /// let mut q_float_list = K::new_float_list(vec![5634.7666, 120.45, 1001.3], qattribute::NONE);
3570    /// let tail = q_float_list.pop_float().unwrap();
3571    /// assert_eq!(tail, 1001.3);
3572    /// ```
3573    pub fn pop_float(&mut self) -> Result<f64> {
3574        if self.is_empty() {
3575            // 0 length
3576            Err(Error::pop_from_empty_list())
3577        } else {
3578            match self.0.qtype {
3579                qtype::FLOAT_LIST => {
3580                    self.decrement();
3581                    Ok(self.as_mut_vec::<F>().unwrap().pop().unwrap())
3582                }
3583                _ => Err(Error::invalid_operation(
3584                    "pop_float",
3585                    self.0.qtype,
3586                    Some(qtype::FLOAT_LIST),
3587                )),
3588            }
3589        }
3590    }
3591
3592    /// Pop a `char` object from q string.
3593    /// # Example
3594    /// ```
3595    /// use kdbplus::qattribute;
3596    /// use kdbplus::ipc::*;
3597    ///
3598    /// let mut q_string = K::new_string(String::from("speedy"), qattribute::NONE);
3599    /// let tail = q_string.pop_char().unwrap();
3600    /// assert_eq!(tail, 'y');
3601    /// ```
3602    pub fn pop_char(&mut self) -> Result<char> {
3603        if self.is_empty() {
3604            // 0 length
3605            Err(Error::pop_from_empty_list())
3606        } else {
3607            match self.0.qtype {
3608                qtype::STRING => Ok(self.as_mut_string().unwrap().pop().unwrap()),
3609                _ => Err(Error::invalid_operation(
3610                    "pop_char",
3611                    self.0.qtype,
3612                    Some(qtype::STRING),
3613                )),
3614            }
3615        }
3616    }
3617
3618    /// Pop a `String` object from q symbol list.
3619    /// # Example
3620    /// ```
3621    /// use kdbplus::qattribute;
3622    /// use kdbplus::ipc::*;
3623    ///
3624    ///let mut q_symbol_list=K::new_symbol_list(vec![String::from("almond"), String::from("macadamia"), String::from("hazel")], qattribute::NONE);
3625    ///let tail=q_symbol_list.pop_symbol().unwrap();
3626    ///assert_eq!(tail, String::from("hazel"));
3627    /// ```
3628    pub fn pop_symbol(&mut self) -> Result<String> {
3629        if self.is_empty() {
3630            // 0 length
3631            Err(Error::pop_from_empty_list())
3632        } else {
3633            match self.0.qtype {
3634                qtype::SYMBOL_LIST => {
3635                    self.decrement();
3636                    Ok(self.as_mut_vec::<S>().unwrap().pop().unwrap())
3637                }
3638                _ => Err(Error::invalid_operation(
3639                    "pop_symbol",
3640                    self.0.qtype,
3641                    Some(qtype::SYMBOL_LIST),
3642                )),
3643            }
3644        }
3645    }
3646
3647    /// Pop a `DateTime<Utc>` object from q timestamp list.
3648    /// # Example
3649    /// ```
3650    /// use kdbplus::qattribute;
3651    /// use kdbplus::ipc::*;
3652    /// use chrono::prelude::*;
3653    ///
3654    /// let mut q_timestamp_list = K::new_timestamp_list(
3655    ///     vec![Utc.ymd(2019, 8, 9).and_hms_nano(16, 28, 2, 468276775)],
3656    ///     qattribute::NONE,
3657    /// );
3658    /// let tail = q_timestamp_list.pop_timestamp().unwrap();
3659    /// assert_eq!(tail, Utc.ymd(2019, 8, 9).and_hms_nano(16, 28, 2, 468276775));
3660    /// ```
3661    pub fn pop_timestamp(&mut self) -> Result<DateTime<Utc>> {
3662        if self.is_empty() {
3663            // 0 length
3664            Err(Error::pop_from_empty_list())
3665        } else {
3666            match self.0.qtype {
3667                qtype::TIMESTAMP_LIST => {
3668                    self.decrement();
3669                    Ok(q_timestamp_to_datetime(
3670                        self.as_mut_vec::<J>().unwrap().pop().unwrap(),
3671                    ))
3672                }
3673                _ => Err(Error::invalid_operation(
3674                    "pop_timestamp",
3675                    self.0.qtype,
3676                    Some(qtype::TIMESTAMP_LIST),
3677                )),
3678            }
3679        }
3680    }
3681
3682    /// Pop a `Date<Utc>` object from q month list.
3683    /// # Example
3684    /// ```
3685    /// use kdbplus::qattribute;
3686    /// use kdbplus::ipc::*;
3687    /// use chrono::prelude::*;
3688    ///
3689    /// let mut q_month_list = K::new_month_list(
3690    ///     vec![
3691    ///         NaiveDate::from_ymd_opt(2011, 5, 1).unwrap(),
3692    ///         NaiveDate::from_ymd_opt(2004, 8, 1).unwrap(),
3693    ///     ],
3694    ///     qattribute::NONE,
3695    /// );
3696    /// let tail = q_month_list.pop_month().unwrap();
3697    /// assert_eq!(tail, NaiveDate::from_ymd_opt(2004, 8, 1).unwrap());
3698    /// ```
3699    pub fn pop_month(&mut self) -> Result<NaiveDate> {
3700        if self.is_empty() {
3701            // 0 length
3702            Err(Error::pop_from_empty_list())
3703        } else {
3704            match self.0.qtype {
3705                qtype::MONTH_LIST => {
3706                    self.decrement();
3707                    Ok(q_month_to_date(
3708                        self.as_mut_vec::<I>().unwrap().pop().unwrap(),
3709                    ))
3710                }
3711                _ => Err(Error::invalid_operation(
3712                    "pop_month",
3713                    self.0.qtype,
3714                    Some(qtype::MONTH_LIST),
3715                )),
3716            }
3717        }
3718    }
3719
3720    /// Pop a `Date<Utc>` object from q date list.
3721    /// # Example
3722    /// ```
3723    /// use kdbplus::qattribute;
3724    /// use kdbplus::ipc::*;
3725    /// use chrono::prelude::*;
3726    ///
3727    /// let mut q_date_list = K::new_date_list(
3728    ///     vec![
3729    ///         NaiveDate::from_ymd_opt(2021, 3, 19).unwrap(),
3730    ///         NaiveDate::from_ymd_opt(2004, 8, 1).unwrap(),
3731    ///         NaiveDate::from_ymd_opt(2014, 6, 4).unwrap(),
3732    ///     ],
3733    ///     qattribute::NONE,
3734    /// );
3735    /// let tail = q_date_list.pop_date().unwrap();
3736    /// assert_eq!(tail, NaiveDate::from_ymd_opt(2014, 6, 4).unwrap());
3737    /// ```
3738    pub fn pop_date(&mut self) -> Result<NaiveDate> {
3739        if self.is_empty() {
3740            // 0 length
3741            Err(Error::pop_from_empty_list())
3742        } else {
3743            match self.0.qtype {
3744                qtype::DATE_LIST => {
3745                    self.decrement();
3746                    Ok(q_date_to_date(
3747                        self.as_mut_vec::<I>().unwrap().pop().unwrap(),
3748                    )?)
3749                }
3750                _ => Err(Error::invalid_operation(
3751                    "pop_date",
3752                    self.0.qtype,
3753                    Some(qtype::DATE_LIST),
3754                )),
3755            }
3756        }
3757    }
3758
3759    /// Pop a `DateTime<Utc>` object from q datetime list.
3760    /// # Example
3761    /// ```
3762    /// use kdbplus::qattribute;
3763    /// use kdbplus::ipc::*;
3764    /// use chrono::prelude::*;
3765    ///
3766    /// let mut q_datetime_list = K::new_datetime_list(
3767    ///     vec![
3768    ///         Utc.ymd(2018, 9, 22).and_hms_milli(4, 58, 30, 204),
3769    ///         Utc.ymd(2003, 12, 9).and_hms_milli(19, 58, 30, 326),
3770    ///     ],
3771    ///     qattribute::NONE,
3772    /// );
3773    /// let tail = q_datetime_list.pop_datetime().unwrap();
3774    /// assert_eq!(tail, Utc.ymd(2003, 12, 9).and_hms_milli(19, 58, 30, 326));
3775    /// ```
3776    pub fn pop_datetime(&mut self) -> Result<DateTime<Utc>> {
3777        if self.is_empty() {
3778            // 0 length
3779            Err(Error::pop_from_empty_list())
3780        } else {
3781            match self.0.qtype {
3782                qtype::DATETIME_LIST => {
3783                    self.decrement();
3784                    Ok(q_datetime_to_datetime(
3785                        self.as_mut_vec::<F>().unwrap().pop().unwrap(),
3786                    ))
3787                }
3788                _ => Err(Error::invalid_operation(
3789                    "pop_datetime",
3790                    self.0.qtype,
3791                    Some(qtype::DATETIME_LIST),
3792                )),
3793            }
3794        }
3795    }
3796
3797    /// Pop a `Duration` object from q timespan list.
3798    /// # Example
3799    /// ```
3800    /// use kdbplus::qattribute;
3801    /// use kdbplus::ipc::*;
3802    /// use chrono::Duration;
3803    ///
3804    /// let mut q_timespan_list = K::new_timespan_list(
3805    ///     vec![
3806    ///         Duration::nanoseconds(6782392639932),
3807    ///         Duration::nanoseconds(219849398328832),
3808    ///     ],
3809    ///     qattribute::NONE,
3810    /// );
3811    /// let tail = q_timespan_list.pop_timespan().unwrap();
3812    /// assert_eq!(tail, Duration::nanoseconds(219849398328832));
3813    /// ```
3814    pub fn pop_timespan(&mut self) -> Result<Duration> {
3815        if self.is_empty() {
3816            // 0 length
3817            Err(Error::pop_from_empty_list())
3818        } else {
3819            match self.0.qtype {
3820                qtype::TIMESPAN_LIST => {
3821                    self.decrement();
3822                    Ok(Duration::nanoseconds(
3823                        self.as_mut_vec::<J>().unwrap().pop().unwrap(),
3824                    ))
3825                }
3826                _ => Err(Error::invalid_operation(
3827                    "pop_timespan",
3828                    self.0.qtype,
3829                    Some(qtype::TIMESPAN_LIST),
3830                )),
3831            }
3832        }
3833    }
3834
3835    /// Pop a `Duration` object from q minute list.
3836    /// # Example
3837    /// ```
3838    /// use kdbplus::qattribute;
3839    /// use kdbplus::ipc::*;
3840    /// use chrono::Duration;
3841    ///
3842    /// let mut q_minute_list = K::new_minute_list(
3843    ///     vec![Duration::minutes(1024), Duration::minutes(-503)],
3844    ///     qattribute::NONE,
3845    /// );
3846    /// let tail = q_minute_list.pop_minute().unwrap();
3847    /// assert_eq!(tail, Duration::minutes(-503));
3848    /// ```
3849    pub fn pop_minute(&mut self) -> Result<Duration> {
3850        if self.is_empty() {
3851            // 0 length
3852            Err(Error::pop_from_empty_list())
3853        } else {
3854            match self.0.qtype {
3855                qtype::MINUTE_LIST => {
3856                    self.decrement();
3857                    Ok(Duration::minutes(
3858                        self.as_mut_vec::<I>().unwrap().pop().unwrap() as i64,
3859                    ))
3860                }
3861                _ => Err(Error::invalid_operation(
3862                    "pop_minute",
3863                    self.0.qtype,
3864                    Some(qtype::MINUTE_LIST),
3865                )),
3866            }
3867        }
3868    }
3869
3870    /// Pop a `Duration` object from q second list.
3871    /// # Example
3872    /// ```
3873    /// use kdbplus::qattribute;
3874    /// use kdbplus::ipc::*;
3875    /// use chrono::Duration;
3876    ///
3877    /// let mut q_second_list = K::new_second_list(
3878    ///     vec![Duration::seconds(-32467), Duration::seconds(73984)],
3879    ///     qattribute::NONE,
3880    /// );
3881    /// let tail = q_second_list.pop_second().unwrap();
3882    /// assert_eq!(tail, Duration::seconds(73984));
3883    /// ```
3884    pub fn pop_second(&mut self) -> Result<Duration> {
3885        if self.is_empty() {
3886            // 0 length
3887            Err(Error::pop_from_empty_list())
3888        } else {
3889            match self.0.qtype {
3890                qtype::SECOND_LIST => {
3891                    self.decrement();
3892                    Ok(Duration::seconds(
3893                        self.as_mut_vec::<I>().unwrap().pop().unwrap() as i64,
3894                    ))
3895                }
3896                _ => Err(Error::invalid_operation(
3897                    "pop_second",
3898                    self.0.qtype,
3899                    Some(qtype::SECOND_LIST),
3900                )),
3901            }
3902        }
3903    }
3904
3905    /// Pop a `Duration` object from q time list.
3906    /// # Example
3907    /// ```
3908    /// use kdbplus::qattribute;
3909    /// use kdbplus::ipc::*;
3910    /// use chrono::Duration;
3911    ///
3912    /// let mut q_time_list = K::new_time_list(
3913    ///     vec![
3914    //             Duration::milliseconds(902467),
3915    ///         Duration::milliseconds(-23587934),
3916    ///     ],
3917    ///     qattribute::NONE,
3918    /// );
3919    /// let tail = q_time_list.pop_time().unwrap();
3920    /// assert_eq!(tail, Duration::milliseconds(-23587934));
3921    /// ```
3922    pub fn pop_time(&mut self) -> Result<Duration> {
3923        if self.is_empty() {
3924            // 0 length
3925            Err(Error::pop_from_empty_list())
3926        } else {
3927            match self.0.qtype {
3928                qtype::TIME_LIST => {
3929                    self.decrement();
3930                    Ok(Duration::milliseconds(
3931                        self.as_mut_vec::<I>().unwrap().pop().unwrap() as i64,
3932                    ))
3933                }
3934                _ => Err(Error::invalid_operation(
3935                    "pop_time",
3936                    self.0.qtype,
3937                    Some(qtype::TIME_LIST),
3938                )),
3939            }
3940        }
3941    }
3942
3943    /// Pop an element as `K` from the tail of the underlying list.
3944    /// # Example
3945    /// ```
3946    /// use kdbplus::qattribute;
3947    /// use kdbplus::ipc::*;
3948    /// use chrono::prelude::*;
3949    /// use chrono::Duration;
3950    ///
3951    /// let mut q_time_list = K::new_time_list(
3952    ///     vec![
3953    ///         Duration::milliseconds(902467),
3954    ///         Duration::milliseconds(-23587934),
3955    ///     ],
3956    ///     qattribute::NONE,
3957    /// );
3958    /// let mut tail = q_time_list.pop().unwrap();
3959    /// assert_eq!(format!("{}", tail), String::from("-06:33:07.934"));
3960    /// let mut q_compound_list = K::new_compound_list(vec![
3961    ///     K::new_long_list(vec![10000324_i64, -43890], qattribute::NONE),
3962    ///     K::new_symbol(String::from("fire")),
3963    ///     K::new_timestamp_list(
3964    ///         vec![
3965    ///             Utc.ymd(2018, 4, 10).and_hms_nano(15, 47, 39, 758934332),
3966    ///             Utc.ymd(2008, 12, 4).and_hms_nano(14, 12, 7, 548932080),
3967    ///         ],
3968    ///         qattribute::NONE,
3969    ///     ),
3970    /// ]);
3971    /// tail = q_compound_list.pop().unwrap();
3972    /// assert_eq!(
3973    ///     format!("{}", tail),
3974    ///     String::from("2018.04.10D15:47:39.758934332 2008.12.04D14:12:07.548932080")
3975    /// );
3976    /// ```
3977    pub fn pop(&mut self) -> Result<K> {
3978        if self.is_empty() {
3979            // 0 length
3980            Err(Error::pop_from_empty_list())
3981        } else {
3982            match self.0.qtype {
3983                qtype::BOOL_LIST => {
3984                    self.decrement();
3985                    Ok(K::new_bool(
3986                        self.as_mut_vec::<G>().unwrap().pop().unwrap() != 0,
3987                    ))
3988                }
3989                qtype::GUID_LIST => {
3990                    self.decrement();
3991                    Ok(K::new_guid(self.as_mut_vec::<U>().unwrap().pop().unwrap()))
3992                }
3993                qtype::BYTE_LIST => {
3994                    self.decrement();
3995                    Ok(K::new_byte(self.as_mut_vec::<G>().unwrap().pop().unwrap()))
3996                }
3997                qtype::SHORT_LIST => {
3998                    self.decrement();
3999                    Ok(K::new_short(self.as_mut_vec::<H>().unwrap().pop().unwrap()))
4000                }
4001                qtype::INT_LIST => {
4002                    self.decrement();
4003                    Ok(K::new_int(self.as_mut_vec::<I>().unwrap().pop().unwrap()))
4004                }
4005                qtype::LONG_LIST => {
4006                    self.decrement();
4007                    Ok(K::new_long(self.as_mut_vec::<J>().unwrap().pop().unwrap()))
4008                }
4009                qtype::REAL_LIST => {
4010                    self.decrement();
4011                    Ok(K::new_real(self.as_mut_vec::<E>().unwrap().pop().unwrap()))
4012                }
4013                qtype::FLOAT_LIST => {
4014                    self.decrement();
4015                    Ok(K::new_float(self.as_mut_vec::<F>().unwrap().pop().unwrap()))
4016                }
4017                qtype::STRING => Ok(K::new_char(self.as_mut_string().unwrap().pop().unwrap())),
4018                qtype::SYMBOL_LIST => {
4019                    self.decrement();
4020                    Ok(K::new_symbol(
4021                        self.as_mut_vec::<S>().unwrap().pop().unwrap(),
4022                    ))
4023                }
4024                qtype::TIMESTAMP_LIST => {
4025                    self.decrement();
4026                    Ok(K::new(
4027                        qtype::TIMESTAMP_ATOM,
4028                        qattribute::NONE,
4029                        k0_inner::long(self.as_mut_vec::<J>().unwrap().pop().unwrap()),
4030                    ))
4031                }
4032                qtype::MONTH_LIST => {
4033                    self.decrement();
4034                    Ok(K::new(
4035                        qtype::MONTH_ATOM,
4036                        qattribute::NONE,
4037                        k0_inner::int(self.as_mut_vec::<I>().unwrap().pop().unwrap()),
4038                    ))
4039                }
4040                qtype::DATE_LIST => {
4041                    self.decrement();
4042                    Ok(K::new(
4043                        qtype::DATE_ATOM,
4044                        qattribute::NONE,
4045                        k0_inner::int(self.as_mut_vec::<I>().unwrap().pop().unwrap()),
4046                    ))
4047                }
4048                qtype::DATETIME_LIST => {
4049                    self.decrement();
4050                    Ok(K::new(
4051                        qtype::DATETIME_ATOM,
4052                        qattribute::NONE,
4053                        k0_inner::float(self.as_mut_vec::<F>().unwrap().pop().unwrap()),
4054                    ))
4055                }
4056                qtype::TIMESPAN_LIST => {
4057                    self.decrement();
4058                    Ok(K::new(
4059                        qtype::TIMESPAN_ATOM,
4060                        qattribute::NONE,
4061                        k0_inner::long(self.as_mut_vec::<J>().unwrap().pop().unwrap()),
4062                    ))
4063                }
4064                qtype::MINUTE_LIST => {
4065                    self.decrement();
4066                    Ok(K::new(
4067                        qtype::MINUTE_ATOM,
4068                        qattribute::NONE,
4069                        k0_inner::int(self.as_mut_vec::<I>().unwrap().pop().unwrap()),
4070                    ))
4071                }
4072                qtype::SECOND_LIST => {
4073                    self.decrement();
4074                    Ok(K::new(
4075                        qtype::SECOND_ATOM,
4076                        qattribute::NONE,
4077                        k0_inner::int(self.as_mut_vec::<I>().unwrap().pop().unwrap()),
4078                    ))
4079                }
4080                qtype::TIME_LIST => {
4081                    self.decrement();
4082                    Ok(K::new(
4083                        qtype::TIME_ATOM,
4084                        qattribute::NONE,
4085                        k0_inner::int(self.as_mut_vec::<I>().unwrap().pop().unwrap()),
4086                    ))
4087                }
4088                qtype::COMPOUND_LIST => {
4089                    self.decrement();
4090                    Ok(self.as_mut_vec::<K>().unwrap().pop().unwrap())
4091                }
4092                _ => Err(Error::invalid_operation("pop", self.0.qtype, None)),
4093            }
4094        }
4095    }
4096
4097    /// Remove a `bool` object from the underlying q bool list.
4098    /// # Example
4099    /// ```
4100    /// use kdbplus::qattribute;
4101    /// use kdbplus::ipc::*;
4102    ///
4103    /// let mut q_bool_list = K::new_bool_list(vec![false, true], qattribute::NONE);
4104    /// let tail = q_bool_list.remove_bool(0).unwrap();
4105    /// assert_eq!(tail, false);
4106    /// ```
4107    pub fn remove_bool(&mut self, index: usize) -> Result<bool> {
4108        if index >= self.len() {
4109            // 0 length
4110            Err(Error::index_out_of_bounds(self.len(), index))
4111        } else {
4112            match self.0.qtype {
4113                qtype::BOOL_LIST => Ok(self.as_mut_vec::<G>().unwrap().remove(index) != 0),
4114                _ => Err(Error::invalid_operation(
4115                    "remove_bool",
4116                    self.0.qtype,
4117                    Some(qtype::BOOL_LIST),
4118                )),
4119            }
4120        }
4121    }
4122
4123    /// Remove a `[u8;16]` object from the underlying q GUID list.
4124    /// # Example
4125    /// ```
4126    /// use kdbplus::qattribute;
4127    /// use kdbplus::ipc::*;
4128    ///
4129    ///let mut q_guid_list=K::new_guid_list(vec![[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]], qattribute::NONE);
4130    ///let tail=q_guid_list.remove_guid(1).unwrap();
4131    ///assert_eq!(tail, [1_u8,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]);
4132    /// ```
4133    pub fn remove_guid(&mut self, index: usize) -> Result<[u8; 16]> {
4134        if index >= self.len() {
4135            // 0 length
4136            Err(Error::index_out_of_bounds(self.len(), index))
4137        } else {
4138            match self.0.qtype {
4139                qtype::GUID_LIST => Ok(self.as_mut_vec::<U>().unwrap().remove(index)),
4140                _ => Err(Error::invalid_operation(
4141                    "remove_guid",
4142                    self.0.qtype,
4143                    Some(qtype::GUID_LIST),
4144                )),
4145            }
4146        }
4147    }
4148
4149    /// Remove a `u8` object from the underlying q byte list.
4150    /// # Example
4151    /// ```
4152    /// use kdbplus::qattribute;
4153    /// use kdbplus::ipc::*;
4154    ///
4155    /// let mut q_byte_list = K::new_byte_list(vec![0x77, 0x99, 0xae], qattribute::NONE);
4156    /// let tail = q_byte_list.remove_byte(1).unwrap();
4157    /// assert_eq!(tail, 0x99_u8);
4158    /// ```
4159    pub fn remove_byte(&mut self, index: usize) -> Result<u8> {
4160        if index >= self.len() {
4161            // 0 length
4162            Err(Error::index_out_of_bounds(self.len(), index))
4163        } else {
4164            match self.0.qtype {
4165                qtype::BYTE_LIST => Ok(self.as_mut_vec::<G>().unwrap().remove(index)),
4166                _ => Err(Error::invalid_operation(
4167                    "remove_byte",
4168                    self.0.qtype,
4169                    Some(qtype::BYTE_LIST),
4170                )),
4171            }
4172        }
4173    }
4174
4175    /// Remove a `i16` object from the underlying q short list.
4176    /// # Example
4177    /// ```
4178    /// use kdbplus::qattribute;
4179    /// use kdbplus::ipc::*;
4180    ///
4181    /// let mut q_short_list = K::new_short_list(vec![12, 50], qattribute::NONE);
4182    /// let tail = q_short_list.remove_short(0).unwrap();
4183    /// assert_eq!(tail, 12_i16);
4184    /// ```
4185    pub fn remove_short(&mut self, index: usize) -> Result<i16> {
4186        if index >= self.len() {
4187            // 0 length
4188            Err(Error::index_out_of_bounds(self.len(), index))
4189        } else {
4190            match self.0.qtype {
4191                qtype::SHORT_LIST => Ok(self.as_mut_vec::<H>().unwrap().remove(index)),
4192                _ => Err(Error::invalid_operation(
4193                    "remove_short",
4194                    self.0.qtype,
4195                    Some(qtype::SHORT_LIST),
4196                )),
4197            }
4198        }
4199    }
4200
4201    /// Remove a `i32` object from the underlying q int list.
4202    /// # Example
4203    /// ```
4204    /// use kdbplus::qattribute;
4205    /// use kdbplus::ipc::*;
4206    ///
4207    /// let mut q_int_list = K::new_int_list(vec![144000, -1, 888], qattribute::NONE);
4208    /// let tail = q_int_list.remove_int(1).unwrap();
4209    /// assert_eq!(tail, -1);
4210    /// ```
4211    pub fn remove_int(&mut self, index: usize) -> Result<i32> {
4212        if index >= self.len() {
4213            // 0 length
4214            Err(Error::index_out_of_bounds(self.len(), index))
4215        } else {
4216            match self.0.qtype {
4217                qtype::INT_LIST => Ok(self.as_mut_vec::<I>().unwrap().remove(index)),
4218                _ => Err(Error::invalid_operation(
4219                    "remove_int",
4220                    self.0.qtype,
4221                    Some(qtype::INT_LIST),
4222                )),
4223            }
4224        }
4225    }
4226
4227    /// Remove a `i64` object from the underlying q long list.
4228    /// # Example
4229    /// ```
4230    /// use kdbplus::qattribute;
4231    /// use kdbplus::ipc::*;
4232    ///
4233    /// let mut q_long_list = K::new_long_list(vec![-86400_i64, 13800000000], qattribute::NONE);
4234    /// let tail = q_long_list.remove_long(0).unwrap();
4235    /// assert_eq!(tail, -86400_i64);
4236    /// ```
4237    pub fn remove_long(&mut self, index: usize) -> Result<i64> {
4238        if index >= self.len() {
4239            // 0 length
4240            Err(Error::index_out_of_bounds(self.len(), index))
4241        } else {
4242            match self.0.qtype {
4243                qtype::LONG_LIST => Ok(self.as_mut_vec::<J>().unwrap().remove(index)),
4244                _ => Err(Error::invalid_operation(
4245                    "remove_long",
4246                    self.0.qtype,
4247                    Some(qtype::LONG_LIST),
4248                )),
4249            }
4250        }
4251    }
4252
4253    /// Remove a `f32` object from the underlying q real list.
4254    /// # Example
4255    /// ```
4256    /// use kdbplus::qattribute;
4257    /// use kdbplus::ipc::*;
4258    ///
4259    /// let mut q_real_list = K::new_real_list(vec![9.22_f32, -0.1], qattribute::NONE);
4260    /// let tail = q_real_list.remove_real(1).unwrap();
4261    /// assert_eq!(tail, -0.1_f32);
4262    /// ```
4263    pub fn remove_real(&mut self, index: usize) -> Result<f32> {
4264        if index >= self.len() {
4265            // 0 length
4266            Err(Error::index_out_of_bounds(self.len(), index))
4267        } else {
4268            match self.0.qtype {
4269                qtype::REAL_LIST => Ok(self.as_mut_vec::<E>().unwrap().remove(index)),
4270                _ => Err(Error::invalid_operation(
4271                    "remove_real",
4272                    self.0.qtype,
4273                    Some(qtype::REAL_LIST),
4274                )),
4275            }
4276        }
4277    }
4278
4279    /// Remove a `f64` object from the underlying q float list.
4280    /// # Example
4281    /// ```
4282    /// use kdbplus::qattribute;
4283    /// use kdbplus::ipc::*;
4284    ///
4285    /// let mut q_float_list = K::new_float_list(vec![5634.7666, 120.45, 1001.3], qattribute::NONE);
4286    /// let tail = q_float_list.remove_float(0).unwrap();
4287    /// assert_eq!(tail, 5634.7666);
4288    /// ```
4289    pub fn remove_float(&mut self, index: usize) -> Result<f64> {
4290        if index >= self.len() {
4291            // 0 length
4292            Err(Error::index_out_of_bounds(self.len(), index))
4293        } else {
4294            match self.0.qtype {
4295                qtype::FLOAT_LIST => Ok(self.as_mut_vec::<F>().unwrap().remove(index)),
4296                _ => Err(Error::invalid_operation(
4297                    "remove_float",
4298                    self.0.qtype,
4299                    Some(qtype::FLOAT_LIST),
4300                )),
4301            }
4302        }
4303    }
4304
4305    /// Remove a `char` object from the underlying q string.
4306    /// # Example
4307    /// ```
4308    /// use kdbplus::qattribute;
4309    /// use kdbplus::ipc::*;
4310    ///
4311    /// let mut q_string = K::new_string(String::from("speedy"), qattribute::NONE);
4312    /// let tail = q_string.remove_char(2).unwrap();
4313    /// assert_eq!(tail, 'e');
4314    /// ```
4315    pub fn remove_char(&mut self, index: usize) -> Result<char> {
4316        if index >= self.len() {
4317            // 0 length
4318            Err(Error::index_out_of_bounds(self.len(), index))
4319        } else {
4320            match self.0.qtype {
4321                qtype::STRING => Ok(self.as_mut_string().unwrap().remove(index)),
4322                _ => Err(Error::invalid_operation(
4323                    "remove_char",
4324                    self.0.qtype,
4325                    Some(qtype::STRING),
4326                )),
4327            }
4328        }
4329    }
4330
4331    /// Remove a `String` object from the underlying q symbol list.
4332    /// # Example
4333    /// ```
4334    /// use kdbplus::qattribute;
4335    /// use kdbplus::ipc::*;
4336    ///
4337    /// let mut q_symbol_list = K::new_symbol_list(
4338    ///     vec![
4339    ///         String::from("almond"),
4340    ///         String::from("macadamia"),
4341    ///         String::from("hazel"),
4342    ///     ],
4343    ///     qattribute::NONE,
4344    /// );
4345    /// let tail = q_symbol_list.remove_symbol(2).unwrap();
4346    /// assert_eq!(tail, String::from("hazel"));
4347    /// ```
4348    pub fn remove_symbol(&mut self, index: usize) -> Result<String> {
4349        if index >= self.len() {
4350            // 0 length
4351            Err(Error::index_out_of_bounds(self.len(), index))
4352        } else {
4353            match self.0.qtype {
4354                qtype::SYMBOL_LIST => Ok(self.as_mut_vec::<S>().unwrap().remove(index)),
4355                _ => Err(Error::invalid_operation(
4356                    "remove_symbol",
4357                    self.0.qtype,
4358                    Some(qtype::SYMBOL_LIST),
4359                )),
4360            }
4361        }
4362    }
4363
4364    /// Remove a `DateTime<Utc>` object from the underlying q timestamp list.
4365    /// # Example
4366    /// ```
4367    /// use kdbplus::qattribute;
4368    /// use kdbplus::ipc::*;
4369    /// use chrono::prelude::*;
4370    ///
4371    /// let mut q_timestamp_list = K::new_timestamp_list(
4372    ///     vec![
4373    ///         Utc.ymd(2019, 8, 9).and_hms_nano(16, 28, 2, 468276775),
4374    ///         Utc.ymd(2015, 3, 28).and_hms_nano(14, 2, 41, 46827329),
4375    ///     ],
4376    ///     qattribute::NONE,
4377    /// );
4378    /// let tail = q_timestamp_list.remove_timestamp(0).unwrap();
4379    /// assert_eq!(tail, Utc.ymd(2019, 8, 9).and_hms_nano(16, 28, 2, 468276775));
4380    /// ```
4381    pub fn remove_timestamp(&mut self, index: usize) -> Result<DateTime<Utc>> {
4382        if index >= self.len() {
4383            // 0 length
4384            Err(Error::index_out_of_bounds(self.len(), index))
4385        } else {
4386            match self.0.qtype {
4387                qtype::TIMESTAMP_LIST => Ok(q_timestamp_to_datetime(
4388                    self.as_mut_vec::<J>().unwrap().remove(index),
4389                )),
4390                _ => Err(Error::invalid_operation(
4391                    "remove_timestamp",
4392                    self.0.qtype,
4393                    Some(qtype::TIMESTAMP_LIST),
4394                )),
4395            }
4396        }
4397    }
4398
4399    /// Remove a `Date<Utc>` object from the underlying q month list.
4400    /// # Example
4401    /// ```
4402    /// use kdbplus::qattribute;
4403    /// use kdbplus::ipc::*;
4404    /// use chrono::prelude::*;
4405    ///
4406    /// let mut q_month_list = K::new_month_list(
4407    ///     vec![
4408    ///         NaiveDate::from_ymd_opt(2011, 5, 1).unwrap(),
4409    ///         NaiveDate::from_ymd_opt(2004, 8, 1).unwrap(),
4410    ///     ],
4411    ///     qattribute::NONE,
4412    /// );
4413    /// let tail = q_month_list.remove_month(0).unwrap();
4414    /// assert_eq!(tail, NaiveDate::from_ymd_opt(2011, 5, 1).unwrap());
4415    /// ```
4416    pub fn remove_month(&mut self, index: usize) -> Result<NaiveDate> {
4417        if index >= self.len() {
4418            // 0 length
4419            Err(Error::index_out_of_bounds(self.len(), index))
4420        } else {
4421            match self.0.qtype {
4422                qtype::MONTH_LIST => Ok(q_month_to_date(
4423                    self.as_mut_vec::<I>().unwrap().remove(index),
4424                )),
4425                _ => Err(Error::invalid_operation(
4426                    "remove_month",
4427                    self.0.qtype,
4428                    Some(qtype::MONTH_LIST),
4429                )),
4430            }
4431        }
4432    }
4433
4434    /// Remove a `Date<Utc>` object from the underlying q date list.
4435    /// # Example
4436    /// ```
4437    /// use kdbplus::qattribute;
4438    /// use kdbplus::ipc::*;
4439    /// use chrono::prelude::*;
4440    ///
4441    /// let mut q_date_list = K::new_date_list(
4442    ///     vec![
4443    ///         NaiveDate::from_ymd_opt(2021, 3, 19).unwrap(),
4444    ///         NaiveDate::from_ymd_opt(2004, 8, 1).unwrap(),
4445    ///         NaiveDate::from_ymd_opt(2014, 6, 4).unwrap(),
4446    ///     ],
4447    ///     qattribute::NONE,
4448    /// );
4449    /// let tail = q_date_list.remove_date(1).unwrap();
4450    /// assert_eq!(tail, NaiveDate::from_ymd_opt(2004, 8, 1).unwrap());
4451    /// ```
4452    pub fn remove_date(&mut self, index: usize) -> Result<NaiveDate> {
4453        if index >= self.len() {
4454            // 0 length
4455            Err(Error::index_out_of_bounds(self.len(), index))
4456        } else {
4457            match self.0.qtype {
4458                qtype::DATE_LIST => Ok(q_date_to_date(
4459                    self.as_mut_vec::<I>().unwrap().remove(index),
4460                )?),
4461                _ => Err(Error::invalid_operation(
4462                    "remove_date",
4463                    self.0.qtype,
4464                    Some(qtype::DATE_LIST),
4465                )),
4466            }
4467        }
4468    }
4469
4470    /// Remove a `DateTime<Utc>` object from the underlying q datetime list.
4471    /// # Example
4472    /// ```
4473    /// use kdbplus::qattribute;
4474    /// use kdbplus::ipc::*;
4475    /// use chrono::prelude::*;
4476    ///
4477    /// let mut q_datetime_list = K::new_datetime_list(
4478    ///     vec![
4479    ///         Utc.ymd(2018, 9, 22).and_hms_milli(4, 58, 30, 204),
4480    ///         Utc.ymd(2003, 12, 9).and_hms_milli(19, 58, 30, 326),
4481    ///     ],
4482    ///     qattribute::NONE,
4483    /// );
4484    /// let tail = q_datetime_list.remove_datetime(1).unwrap();
4485    /// assert_eq!(tail, Utc.ymd(2003, 12, 9).and_hms_milli(19, 58, 30, 326));
4486    /// ```
4487    pub fn remove_datetime(&mut self, index: usize) -> Result<DateTime<Utc>> {
4488        if index >= self.len() {
4489            // 0 length
4490            Err(Error::index_out_of_bounds(self.len(), index))
4491        } else {
4492            match self.0.qtype {
4493                qtype::DATETIME_LIST => Ok(q_datetime_to_datetime(
4494                    self.as_mut_vec::<F>().unwrap().remove(index),
4495                )),
4496                _ => Err(Error::invalid_operation(
4497                    "remove_datetime",
4498                    self.0.qtype,
4499                    Some(qtype::DATETIME_LIST),
4500                )),
4501            }
4502        }
4503    }
4504
4505    /// Remove a `Duration` object from the underlying q timespan list.
4506    /// # Example
4507    /// ```
4508    /// use kdbplus::qattribute;
4509    /// use kdbplus::ipc::*;
4510    /// use chrono::Duration;
4511    ///
4512    /// let mut q_timespan_list = K::new_timespan_list(
4513    ///     vec![
4514    ///         Duration::nanoseconds(6782392639932),
4515    ///         Duration::nanoseconds(219849398328832),
4516    ///     ],
4517    ///     qattribute::NONE,
4518    /// );
4519    /// let tail = q_timespan_list.remove_timespan(0).unwrap();
4520    /// assert_eq!(tail, Duration::nanoseconds(6782392639932));
4521    /// ```
4522    pub fn remove_timespan(&mut self, index: usize) -> Result<Duration> {
4523        if index >= self.len() {
4524            // 0 length
4525            Err(Error::index_out_of_bounds(self.len(), index))
4526        } else {
4527            match self.0.qtype {
4528                qtype::TIMESPAN_LIST => Ok(Duration::nanoseconds(
4529                    self.as_mut_vec::<J>().unwrap().remove(index),
4530                )),
4531                _ => Err(Error::invalid_operation(
4532                    "remove_timespan",
4533                    self.0.qtype,
4534                    Some(qtype::TIMESPAN_LIST),
4535                )),
4536            }
4537        }
4538    }
4539
4540    /// Remove a `Duration` object from the underlying q minute list.
4541    /// # Example
4542    /// ```
4543    /// use kdbplus::qattribute;
4544    /// use kdbplus::ipc::*;
4545    /// use chrono::Duration;
4546    ///
4547    /// let mut q_minute_list = K::new_minute_list(
4548    ///     vec![Duration::minutes(1024), Duration::minutes(-503)],
4549    ///     qattribute::NONE,
4550    /// );
4551    /// let tail = q_minute_list.remove_minute(1).unwrap();
4552    /// assert_eq!(tail, Duration::minutes(-503));
4553    /// ```
4554    pub fn remove_minute(&mut self, index: usize) -> Result<Duration> {
4555        if index >= self.len() {
4556            // 0 length
4557            Err(Error::index_out_of_bounds(self.len(), index))
4558        } else {
4559            match self.0.qtype {
4560                qtype::MINUTE_LIST => Ok(Duration::minutes(
4561                    self.as_mut_vec::<I>().unwrap().remove(index) as i64,
4562                )),
4563                _ => Err(Error::invalid_operation(
4564                    "remove_minute",
4565                    self.0.qtype,
4566                    Some(qtype::MINUTE_LIST),
4567                )),
4568            }
4569        }
4570    }
4571
4572    /// Remove a `Duration` object from the underlying q second list.
4573    /// # Example
4574    /// ```
4575    /// use kdbplus::qattribute;
4576    /// use kdbplus::ipc::*;
4577    /// use chrono::Duration;
4578    ///
4579    /// let mut q_second_list = K::new_second_list(
4580    ///     vec![Duration::seconds(-32467), Duration::seconds(73984)],
4581    ///     qattribute::NONE,
4582    /// );
4583    /// let tail = q_second_list.remove_second(0).unwrap();
4584    /// assert_eq!(tail, Duration::seconds(-32467));
4585    /// ```
4586    pub fn remove_second(&mut self, index: usize) -> Result<Duration> {
4587        if index >= self.len() {
4588            // 0 length
4589            Err(Error::index_out_of_bounds(self.len(), index))
4590        } else {
4591            match self.0.qtype {
4592                qtype::SECOND_LIST => Ok(Duration::seconds(
4593                    self.as_mut_vec::<I>().unwrap().remove(index) as i64,
4594                )),
4595                _ => Err(Error::invalid_operation(
4596                    "remove_second",
4597                    self.0.qtype,
4598                    Some(qtype::SECOND_LIST),
4599                )),
4600            }
4601        }
4602    }
4603
4604    /// Remove a `Duration` object from the underlying q time list.
4605    /// # Example
4606    /// ```
4607    /// use kdbplus::qattribute;
4608    /// use kdbplus::ipc::*;
4609    /// use chrono::Duration;
4610    ///
4611    /// let mut q_time_list = K::new_time_list(
4612    ///     vec![
4613    ///         Duration::milliseconds(902467),
4614    ///         Duration::milliseconds(-23587934),
4615    ///         Duration::milliseconds(278958528),
4616    ///     ],
4617    ///     qattribute::NONE,
4618    /// );
4619    /// let tail = q_time_list.remove_time(2).unwrap();
4620    /// assert_eq!(tail, Duration::milliseconds(278958528));
4621    /// ```
4622    pub fn remove_time(&mut self, index: usize) -> Result<Duration> {
4623        if index >= self.len() {
4624            // 0 length
4625            Err(Error::index_out_of_bounds(self.len(), index))
4626        } else {
4627            match self.0.qtype {
4628                qtype::TIME_LIST => Ok(Duration::milliseconds(
4629                    self.as_mut_vec::<I>().unwrap().remove(index) as i64,
4630                )),
4631                _ => Err(Error::invalid_operation(
4632                    "remove_time",
4633                    self.0.qtype,
4634                    Some(qtype::TIME_LIST),
4635                )),
4636            }
4637        }
4638    }
4639
4640    /// Remove an element as `K` object from the underlying q list.
4641    ///  # Example
4642    /// ```
4643    /// use kdbplus::qattribute;
4644    /// use kdbplus::ipc::*;
4645    /// use chrono::prelude::*;
4646    /// use chrono::Duration;
4647    ///
4648    /// let mut q_time_list = K::new_time_list(
4649    ///     vec![
4650    ///         Duration::milliseconds(902467),
4651    ///         Duration::milliseconds(-23587934),
4652    ///     ],
4653    ///     qattribute::NONE,
4654    /// );
4655    /// let mut tail = q_time_list.remove(1).unwrap();
4656    /// assert_eq!(format!("{}", tail), String::from("-06:33:07.934"));
4657    ///
4658    /// let mut q_compound_list = K::new_compound_list(vec![
4659    ///     K::new_long_list(vec![10000324_i64, -43890], qattribute::UNIQUE),
4660    ///     K::new_symbol(String::from("fire")),
4661    ///     K::new_timestamp_list(
4662    ///         vec![
4663    ///             Utc.ymd(2018, 4, 10).and_hms_nano(15, 47, 39, 758934332),
4664    ///             Utc.ymd(2008, 12, 4).and_hms_nano(14, 12, 7, 548932080),
4665    ///         ],
4666    ///         qattribute::NONE,
4667    ///     ),
4668    /// ]);
4669    /// tail = q_compound_list.remove(0).unwrap();
4670    /// assert_eq!(format!("{}", tail), String::from("`u#10000324 -43890"));
4671    /// ```
4672    pub fn remove(&mut self, index: usize) -> Result<K> {
4673        if index >= self.len() {
4674            // 0 length
4675            Err(Error::index_out_of_bounds(self.len(), index))
4676        } else {
4677            match self.0.qtype {
4678                qtype::BOOL_LIST => Ok(K::new_bool(
4679                    self.as_mut_vec::<G>().unwrap().remove(index) != 0,
4680                )),
4681                qtype::GUID_LIST => Ok(K::new_guid(self.as_mut_vec::<U>().unwrap().remove(index))),
4682                qtype::BYTE_LIST => Ok(K::new_byte(self.as_mut_vec::<G>().unwrap().remove(index))),
4683                qtype::SHORT_LIST => {
4684                    Ok(K::new_short(self.as_mut_vec::<H>().unwrap().remove(index)))
4685                }
4686                qtype::INT_LIST => Ok(K::new_int(self.as_mut_vec::<I>().unwrap().remove(index))),
4687                qtype::LONG_LIST => Ok(K::new_long(self.as_mut_vec::<J>().unwrap().remove(index))),
4688                qtype::REAL_LIST => Ok(K::new_real(self.as_mut_vec::<E>().unwrap().remove(index))),
4689                qtype::FLOAT_LIST => {
4690                    Ok(K::new_float(self.as_mut_vec::<F>().unwrap().remove(index)))
4691                }
4692                qtype::STRING => Ok(K::new_char(self.as_mut_string().unwrap().remove(index))),
4693                qtype::SYMBOL_LIST => {
4694                    Ok(K::new_symbol(self.as_mut_vec::<S>().unwrap().remove(index)))
4695                }
4696                qtype::TIMESTAMP_LIST => Ok(K::new_timestamp(q_timestamp_to_datetime(
4697                    self.as_mut_vec::<J>().unwrap().remove(index),
4698                ))),
4699                qtype::MONTH_LIST => Ok(K::new_month(q_month_to_date(
4700                    self.as_mut_vec::<I>().unwrap().remove(index),
4701                ))),
4702                qtype::DATE_LIST => Ok(K::new_date(q_date_to_date(
4703                    self.as_mut_vec::<I>().unwrap().remove(index),
4704                )?)),
4705                qtype::DATETIME_LIST => Ok(K::new_datetime(q_datetime_to_datetime(
4706                    self.as_mut_vec::<F>().unwrap().remove(index),
4707                ))),
4708                qtype::TIMESPAN_LIST => Ok(K::new_timespan(Duration::nanoseconds(
4709                    self.as_mut_vec::<J>().unwrap().remove(index),
4710                ))),
4711                qtype::MINUTE_LIST => Ok(K::new_minute(Duration::minutes(
4712                    self.as_mut_vec::<I>().unwrap().remove(index) as i64,
4713                ))),
4714                qtype::SECOND_LIST => Ok(K::new_second(Duration::seconds(
4715                    self.as_mut_vec::<I>().unwrap().remove(index) as i64,
4716                ))),
4717                qtype::TIME_LIST => Ok(K::new_time(Duration::milliseconds(
4718                    self.as_mut_vec::<I>().unwrap().remove(index) as i64,
4719                ))),
4720                qtype::COMPOUND_LIST => Ok(self.as_mut_vec::<K>().unwrap().remove(index)),
4721                _ => Err(Error::invalid_operation("remove", self.0.qtype, None)),
4722            }
4723        }
4724    }
4725
4726    /// Add a pair of key-value to a q dictionary.
4727    /// # Example
4728    /// ```
4729    /// use kdbplus::qattribute;
4730    /// use kdbplus::ipc::*;
4731    /// use chrono::prelude::*;
4732    ///
4733    /// let keys = K::new_int_list(vec![0, 1, 2], qattribute::NONE);
4734    /// let values = K::new_date_list(
4735    ///     vec![
4736    ///         NaiveDate::from_ymd_opt(2000, 1, 9).unwrap(),
4737    ///         NaiveDate::from_ymd_opt(2001, 4, 10).unwrap(),
4738    ///         NaiveDate::from_ymd_opt(2015, 3, 16).unwrap(),
4739    ///     ],
4740    ///     qattribute::NONE,
4741    /// );
4742    /// let mut q_dictionary = K::new_dictionary(keys, values).unwrap();
4743    ///
4744    /// q_dictionary
4745    ///     .push_pair(&3, &NaiveDate::from_ymd_opt(2020, 8, 9).unwrap())
4746    ///     .unwrap();
4747    /// assert_eq!(
4748    ///     format!("{}", q_dictionary),
4749    ///     String::from("0 1 2 3i!2000.01.09 2001.04.10 2015.03.16 2020.08.09")
4750    /// );
4751    /// ```
4752    pub fn push_pair(&mut self, key: &dyn Any, value: &dyn Any) -> Result<()> {
4753        match self.0.qtype {
4754            qtype::DICTIONARY => {
4755                let dictionary = self.as_mut_vec::<K>().unwrap();
4756                match dictionary[0].push(key) {
4757                    Ok(_) => match dictionary[1].push(value) {
4758                        Ok(_) => Ok(()),
4759                        Err(error) => {
4760                            // Revert the change to the key
4761                            dictionary[0].pop().unwrap();
4762                            Err(error)
4763                        }
4764                    },
4765                    Err(error) => Err(error),
4766                }
4767            }
4768            _ => Err(Error::invalid_operation(
4769                "push_pair",
4770                self.0.qtype,
4771                Some(qtype::DICTIONARY),
4772            )),
4773        }
4774    }
4775
4776    /// Pop the last key-vaue pair from a q dictionary.
4777    /// # Example
4778    /// ```
4779    /// use kdbplus::qattribute;
4780    /// use kdbplus::ipc::*;
4781    /// use chrono::prelude::*;
4782    ///
4783    /// let keys = K::new_int_list(vec![0, 1, 2], qattribute::NONE);
4784    /// let values = K::new_date_list(
4785    ///     vec![
4786    ///         NaiveDate::from_ymd_opt(2000, 1, 9).unwrap(),
4787    ///         NaiveDate::from_ymd_opt(2001, 4, 10).unwrap(),
4788    ///         NaiveDate::from_ymd_opt(2015, 3, 16).unwrap(),
4789    ///     ],
4790    ///     qattribute::NONE,
4791    /// );
4792    /// let mut q_dictionary = K::new_dictionary(keys, values).unwrap();
4793    ///
4794    /// q_dictionary.pop_pair().unwrap();
4795    /// assert_eq!(
4796    ///     format!("{}", q_dictionary),
4797    ///     String::from("0 1i!2000.01.09 2001.04.10")
4798    /// );
4799    /// ```
4800    pub fn pop_pair(&mut self) -> Result<(K, K)> {
4801        match self.0.qtype {
4802            qtype::DICTIONARY => {
4803                let dictionary = self.as_mut_vec::<K>().unwrap();
4804                if let (Ok(key), Ok(value)) = (dictionary[0].pop(), dictionary[1].pop()) {
4805                    Ok((key, value))
4806                } else {
4807                    // Dictionary type assures the result is one of failure for both key and value, or success for both key and value.
4808                    Err(Error::pop_from_empty_list())
4809                }
4810            }
4811            _ => Err(Error::invalid_operation(
4812                "pop_pair",
4813                self.0.qtype,
4814                Some(qtype::DICTIONARY),
4815            )),
4816        }
4817    }
4818
4819    /// Get the length of q object. The meaning of the returned value varies according to the type:
4820    /// - atom: 1
4821    /// - list: The number of elements in the list.
4822    /// - table: The number of rows.
4823    /// - dictionary: The number of keys.
4824    /// - general null: 1
4825    /// # Example
4826    /// ```
4827    /// use kdbplus::qattribute;
4828    /// use kdbplus::ipc::*;
4829    /// use chrono::prelude::*;
4830    ///
4831    /// let q_symbol_list = K::new_symbol_list(
4832    ///     vec![
4833    ///         String::from("almond"),
4834    ///         String::from("macadamia"),
4835    ///         String::from("hazel"),
4836    ///     ],
4837    ///     qattribute::NONE,
4838    /// );
4839    /// assert_eq!(q_symbol_list.len(), 3);
4840    ///
4841    /// let keys = K::new_int_list(vec![0, 1, 2], qattribute::NONE);
4842    /// let values = K::new_date_list(
4843    ///     vec![
4844    ///         NaiveDate::from_ymd_opt(2000, 1, 9).unwrap(),
4845    ///         NaiveDate::from_ymd_opt(2001, 4, 10).unwrap(),
4846    ///         NaiveDate::from_ymd_opt(2015, 3, 16).unwrap(),
4847    ///     ],
4848    ///     qattribute::NONE,
4849    /// );
4850    /// let mut q_dictionary = K::new_dictionary(keys, values).unwrap();
4851    /// assert_eq!(q_dictionary.len(), 3);
4852    /// ```
4853    pub fn len(&self) -> usize {
4854        match self.0.qtype {
4855            _t @ qtype::COMPOUND_LIST..=qtype::TIME_LIST => {
4856                // List
4857                match &self.0.value {
4858                    // string is stored as symbol (`String`).
4859                    k0_inner::symbol(string) => string.len(),
4860                    // The other lists.
4861                    k0_inner::list(list) => list.n as usize,
4862                    _ => unreachable!(),
4863                }
4864            }
4865            qtype::TABLE => {
4866                // Table
4867                match &self.0.value {
4868                    k0_inner::table(dictionary) => {
4869                        // Dictionary is a vector of [K (keys), K (values)]
4870                        // values is assured to be a list of K as this is a table type.
4871                        // Retrieve the first column and get its length.
4872                        match &dictionary.as_vec::<K>().unwrap()[1].as_vec::<K>().unwrap()[0]
4873                            .0
4874                            .value
4875                        {
4876                            k0_inner::list(column) => {
4877                                // Return the number of rows
4878                                column.n as usize
4879                            }
4880                            k0_inner::symbol(column) => {
4881                                // char column
4882                                // Return the number of rows
4883                                column.len()
4884                            }
4885                            _ => unreachable!(),
4886                        }
4887                    }
4888                    _ => unreachable!(),
4889                }
4890            }
4891            qtype::DICTIONARY | qtype::SORTED_DICTIONARY => {
4892                // Dictionary is a vector of [K (keys), K (values)]
4893                // Get keys and return its length.
4894                match &self.as_vec::<K>().unwrap()[0].0.value {
4895                    k0_inner::list(list) => list.n as usize,
4896                    // Keyed table
4897                    // Get the number of rows by deligating it to table.len()
4898                    k0_inner::table(_) => self.as_vec::<K>().unwrap()[0].len(),
4899                    _ => unreachable!(),
4900                }
4901            }
4902            // Atom and general null
4903            _ => 1,
4904        }
4905    }
4906
4907    /// Check if the underlying value is empty.
4908    pub fn is_empty(&self) -> bool {
4909        self.len() == 0
4910    }
4911
4912    /// Create a table object from a dictionary object. Return value is either of:
4913    /// - `Err(original value)`: If the argument is not a dictionary. The returned object
4914    ///   is wrapped in error enum and can be retrieved by [`into_inner`](error/enum.Error.html#method.into_inner).
4915    /// - `Ok(table)`: In case of successful conversion.
4916    /// # Note
4917    /// - Key type must be a symbol.
4918    /// - This function does not check if lengths of columns are same.
4919    /// # Example
4920    /// ```
4921    /// use kdbplus::qattribute;
4922    /// use kdbplus::ipc::*;
4923    ///
4924    /// let q_dictionary = K::new_dictionary(
4925    ///     K::new_symbol_list(
4926    ///         vec![String::from("a"), String::from("b"), String::from("c")],
4927    ///         qattribute::NONE,
4928    ///     ),
4929    ///     K::new_compound_list(vec![
4930    ///         K::new_int_list(vec![10, 20, 30], qattribute::NONE),
4931    ///         K::new_symbol_list(
4932    ///             vec![
4933    ///                 String::from("honey"),
4934    ///                 String::from("sugar"),
4935    ///                 String::from("maple"),
4936    ///             ],
4937    ///             qattribute::NONE,
4938    ///         ),
4939    ///         K::new_bool_list(vec![false, false, true], qattribute::NONE),
4940    ///     ]),
4941    /// )
4942    /// .unwrap();
4943    ///
4944    /// let q_table = q_dictionary.flip().unwrap();
4945    /// assert_eq!(
4946    ///     format!("{}", q_table),
4947    ///     String::from("+`a`b`c!(10 20 30i;`honey`sugar`maple;001b)")
4948    /// );
4949    /// ```
4950    pub fn flip(self) -> Result<Self> {
4951        match self.0.qtype {
4952            qtype::DICTIONARY | qtype::SORTED_DICTIONARY => {
4953                let keys_values = self.as_vec::<K>().unwrap();
4954                if keys_values[0].0.qtype == qtype::SYMBOL_LIST
4955                    && keys_values[1].0.qtype == qtype::COMPOUND_LIST
4956                {
4957                    Ok(K::new(
4958                        qtype::TABLE,
4959                        qattribute::NONE,
4960                        k0_inner::table(self),
4961                    ))
4962                } else {
4963                    Err(Error::object(self))
4964                }
4965            }
4966            // Failed to convert. Return the original argument.
4967            _ => Err(Error::object(self)),
4968        }
4969    }
4970
4971    /// Convert a table into a keyed table with the first `n` columns ebing keys.
4972    ///  In case of error for type mismatch the original object is returned wrapped
4973    ///  in error enum and can be retrieved by [`into_inner`](error/enum.Error.html#method.into_inner).
4974    ///  # Example
4975    /// ```
4976    /// use kdbplus::qattribute;
4977    /// use kdbplus::ipc::*;
4978    ///
4979    /// let q_dictionary = K::new_dictionary(
4980    ///     K::new_symbol_list(
4981    ///         vec![String::from("a"), String::from("b"), String::from("c")],
4982    ///         qattribute::NONE,
4983    ///     ),
4984    ///     K::new_compound_list(vec![
4985    ///         K::new_int_list(vec![10, 20, 30], qattribute::NONE),
4986    ///         K::new_symbol_list(
4987    ///             vec![
4988    ///                 String::from("honey"),
4989    ///                 String::from("sugar"),
4990    ///                 String::from("maple"),
4991    ///             ],
4992    ///             qattribute::NONE,
4993    ///         ),
4994    ///         K::new_bool_list(vec![false, false, true], qattribute::NONE),
4995    ///     ]),
4996    /// )
4997    /// .unwrap();
4998    ///
4999    /// let q_table = q_dictionary.flip().unwrap();
5000    /// let q_keyed_table = q_table.enkey(1).unwrap();
5001    /// assert_eq!(
5002    ///     format!("{}", q_keyed_table),
5003    ///     String::from("(+,`a!,10 20 30i)!(+`b`c!(`honey`sugar`maple;001b))")
5004    /// );
5005    /// ```
5006    pub fn enkey(self, mut n: usize) -> Result<Self> {
5007        match self.0.value {
5008            k0_inner::table(mut dictionary) => {
5009                let headers_columns = dictionary.as_mut_vec::<K>().unwrap();
5010                if headers_columns[0].len() <= n {
5011                    // Maximum number of keys are #columns - 1
5012                    n = headers_columns[0].len() - 1;
5013                }
5014                let value_heders = K::new_symbol_list(
5015                    headers_columns[0].as_mut_vec::<S>().unwrap().split_off(n),
5016                    qattribute::NONE,
5017                );
5018                let value_columns = K::new_compound_list(
5019                    headers_columns[1].as_mut_vec::<K>().unwrap().split_off(n),
5020                );
5021                // Build value table
5022                let value_table = K::new_dictionary(value_heders, value_columns)
5023                    .unwrap()
5024                    .flip()
5025                    .unwrap();
5026                Ok(K::new_dictionary(dictionary.flip().unwrap(), value_table)
5027                    .expect("failed to build keyed table"))
5028            }
5029            // Not a table. Return the original argument.
5030            _ => Err(Error::object(self)),
5031        }
5032    }
5033
5034    /// Convert a keyed table into an ordinary table. In case of error for type mismatch
5035    ///  the original object is returned wrapped in error enum and can be retrieved by [`into_inner`](error/enum.Error.html#method.into_inner).
5036    /// # Example
5037    /// ```
5038    /// use kdbplus::qattribute;
5039    /// use kdbplus::ipc::*;
5040    ///
5041    /// let q_dictionary = K::new_dictionary(
5042    ///     K::new_symbol_list(
5043    ///         vec![String::from("a"), String::from("b"), String::from("c")],
5044    ///         qattribute::NONE,
5045    ///     ),
5046    ///     K::new_compound_list(vec![
5047    ///         K::new_int_list(vec![10, 20, 30], qattribute::NONE),
5048    ///         K::new_symbol_list(
5049    ///             vec![
5050    ///                 String::from("honey"),
5051    ///                 String::from("sugar"),
5052    ///                 String::from("maple"),
5053    ///             ],
5054    ///             qattribute::NONE,
5055    ///         ),
5056    ///         K::new_bool_list(vec![false, false, true], qattribute::NONE),
5057    ///     ]),
5058    /// )
5059    /// .unwrap();
5060    ///
5061    /// let q_table = q_dictionary.flip().unwrap();
5062    /// let q_keyed_table = q_table.enkey(1).unwrap();
5063    /// assert_eq!(
5064    ///     format!("{}", q_keyed_table),
5065    ///     String::from("(+,`a!,10 20 30i)!(+`b`c!(`honey`sugar`maple;001b))")
5066    /// );
5067    /// let revived_table = q_keyed_table.unkey().unwrap();
5068    /// assert_eq!(
5069    ///     format!("{}", revived_table),
5070    ///     String::from("+`a`b`c!(10 20 30i;`honey`sugar`maple;001b)")
5071    /// );
5072    /// ```
5073    pub fn unkey(mut self) -> Result<Self> {
5074        match self.0.qtype {
5075            qtype::DICTIONARY => {
5076                // Key table and value table
5077                let value_table = self.as_mut_vec::<K>().unwrap().pop().unwrap();
5078                let key_table = self.as_mut_vec::<K>().unwrap().pop().unwrap();
5079                match (key_table.0.value, value_table.0.value) {
5080                    (
5081                        k0_inner::table(mut key_dictionary),
5082                        k0_inner::table(mut value_dictionary),
5083                    ) => {
5084                        // Key dictionary and value dictionary
5085                        key_dictionary
5086                            .as_mut_vec::<K>()
5087                            .unwrap()
5088                            .iter_mut()
5089                            .zip(&mut *value_dictionary.as_mut_vec::<K>().unwrap())
5090                            .enumerate()
5091                            .for_each(|(i, (key, value))| {
5092                                // Merge key component and value component
5093                                if i == 0 {
5094                                    // Header
5095                                    key.as_mut_vec::<S>()
5096                                        .unwrap()
5097                                        .append(value.as_mut_vec::<S>().unwrap());
5098                                } else {
5099                                    // Column
5100                                    key.as_mut_vec::<K>()
5101                                        .unwrap()
5102                                        .append(value.as_mut_vec::<K>().unwrap());
5103                                }
5104                            });
5105                        // Flip joint dictionary to table
5106                        key_dictionary.flip()
5107                    }
5108                    _ => unreachable!(),
5109                }
5110            }
5111            // Not a keyed table. Return the original argument.
5112            _ => Err(Error::object(self)),
5113        }
5114    }
5115}
5116
5117//++++++++++++++++++++++++++++++++++++++++++++++++++//
5118// >> Private Functions
5119//++++++++++++++++++++++++++++++++++++++++++++++++++//
5120
5121//%% Constructors //%%vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
5122
5123/// Convert `DateTime<Utc>` into `i64`. The returned value is an elapsed time in nanoseconds since `2000.01.01D00:00:00`.
5124fn datetime_to_q_timestamp(timestamp: DateTime<Utc>) -> i64 {
5125    // q          |----------------------------------------|
5126    // Rust  |----------------------------------------------------|
5127
5128    if timestamp <= *qnull::TIMESTAMP {
5129        // 0Np
5130        qnull_base::J
5131    } else if timestamp == *qninf::TIMESTAMP {
5132        // -0Wp
5133        qninf_base::J
5134    } else if timestamp >= *qinf::TIMESTAMP {
5135        // 0Wp
5136        qinf_base::J
5137    } else {
5138        timestamp
5139            .timestamp_nanos_opt()
5140            .unwrap()
5141            .saturating_sub(KDB_TIMESTAMP_OFFSET)
5142    }
5143}
5144
5145/// Convert `Date<Utc>` into `i32`. The returned value is an elapsed time in months since `2000.01.01`.
5146fn date_to_q_month(month: NaiveDate) -> i32 {
5147    // q     |------------------------------------------------------|
5148    // Rust        |----------------------------------------|
5149
5150    if month == qnull::MONTH {
5151        // 0Nm
5152        qnull_base::I
5153    } else if month == *qninf::MONTH {
5154        // -0Wm
5155        qninf_base::I
5156    } else if month >= *qinf::MONTH {
5157        // 0Wm
5158        qinf_base::I
5159    } else {
5160        let months = (month.year() - 1970) * 12 + month.month0() as i32;
5161        months.saturating_sub(KDB_MONTH_OFFSET)
5162    }
5163}
5164
5165/// Convert `Date<Utc>` into `i32`. The returned value is an elapsed time in days since `2000.01.01`.
5166fn date_to_q_date(date: NaiveDate) -> i32 {
5167    // q     |------------------------------------------------------|
5168    // Rust        |-----------------------------------------|
5169
5170    if date == qnull::DATE {
5171        // 0Nd
5172        qnull_base::I
5173    } else if date == *qninf::DATE {
5174        // -0Wd
5175        qninf_base::I
5176    } else if date == qinf::DATE {
5177        // 0Wd
5178        qinf_base::I
5179    } else {
5180        let days =
5181            NaiveDate::signed_duration_since(date, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap())
5182                .num_days() as i32;
5183        days.saturating_sub(KDB_DAY_OFFSET)
5184    }
5185}
5186
5187/// Convert `Date<Utc>` into `i32`. The returned value is an elapsed time in days since `2000.01.01`.
5188fn datetime_to_q_datetime(datetime: DateTime<Utc>) -> f64 {
5189    // q     |------------------------------------------------------|
5190    // Rust        |-----------------------------------------|
5191
5192    if datetime == qnull::DATETIME {
5193        // 0Nz
5194        qnull_base::F
5195    } else if datetime <= *qninf::DATETIME {
5196        // -0Wz
5197        qninf_base::F
5198    } else if datetime >= *qinf::DATETIME {
5199        // 0Wz
5200        qinf_base::F
5201    } else {
5202        let millis = datetime.timestamp_millis() as f64 / ONE_DAY_MILLIS as f64;
5203        millis - KDB_DAY_OFFSET as f64
5204    }
5205}
5206
5207//%% Getter //%%vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
5208
5209/// Convert q timestamp (elapsed time in nanoseconds since `2000.01.01D00:00:00`) into `DateTime<Utc>`.
5210pub(crate) fn q_timestamp_to_datetime(nanos: i64) -> DateTime<Utc> {
5211    // q          |----------------------------------------|
5212    // Rust  |----------------------------------------------------|
5213
5214    // Add duration to avoid overflow
5215    Utc.timestamp_nanos(nanos) + Duration::nanoseconds(KDB_TIMESTAMP_OFFSET)
5216}
5217
5218/// Convert q month (elapsed time in months since `2000.01.01`) into `Date<Utc>`.
5219pub(crate) fn q_month_to_date(months: i32) -> NaiveDate {
5220    // q     |------------------------------------------------------|
5221    // Rust        |-----------------------------------------|
5222
5223    if months == qnull_base::I {
5224        qnull::MONTH
5225    } else if months <= -3171072 {
5226        // Consider pulling month value from q, not only reverse Rust->q.
5227        // Convert Date::signed_duration_since(chrono::MIN_DATE, Utc.ymd(2000, 1,1)).num_days()) into months
5228        //  with 1461 as 4 years, 36525 as 100 years and 146097 as 400 years
5229        *qninf::MONTH
5230    } else if months >= 3121728 {
5231        // Consider pulling month value from q, not only reverse Rust->q.
5232        // Convert Date::signed_duration_since(chrono::MAX_DATE - Duration::days(30), Utc.ymd(2000, 1,1)).num_days()) into months
5233        //  with 1461 as 4 years, 36525 as 100 years and 146097 as 400 years
5234        *qinf::MONTH
5235    } else {
5236        NaiveDate::from_ymd_opt(2000 + months / 12, 1 + (months % 12) as u32, 1).unwrap()
5237    }
5238}
5239
5240/// Convert q month (elapsed time in days since `2000.01.01`) into `Date<Utc>`.
5241pub(crate) fn q_date_to_date(days: i32) -> Result<NaiveDate> {
5242    // q     |------------------------------------------------------|
5243    // Rust        |-----------------------------------------|
5244
5245    if days == qnull_base::I {
5246        Ok(qnull::DATE)
5247    } else if days <= -96476615 {
5248        // Consider pulling date value from q, not only reverse Rust->q.
5249        // Date::signed_duration_since(chrono::MIN_DATE, Utc.ymd(2000, 1,1)).num_days())
5250        Ok(*qninf::DATE)
5251    } else if days >= 95015644 {
5252        // Consider pulling date value from q, not only reverse Rust->q.
5253        // Date::signed_duration_since(chrono::MAX_DATE, Utc.ymd(2000, 1,1)).num_days())
5254        Ok(qinf::DATE)
5255    } else {
5256        Ok((NaiveDate::from_ymd_opt(2000, 1, 1)
5257            .ok_or_else(|| Error::InvalidDateTime)?
5258            .and_hms_opt(0, 0, 0)
5259            .ok_or_else(|| Error::InvalidDateTime)?
5260            .and_local_timezone(Utc)
5261            .unwrap()
5262            + Duration::days(days as i64))
5263        .date_naive())
5264    }
5265}
5266
5267/// Convert q datetime (elapsed time in days with glanularity of milliseconds since `2000.01.01T00:00:00`) into `DateTime<Utc>`.
5268pub(crate) fn q_datetime_to_datetime(days: f64) -> DateTime<Utc> {
5269    // q     |------------------------------------------------------|
5270    // Rust        |-----------------------------------------|
5271
5272    if days.is_nan() {
5273        qnull::DATETIME
5274    } else if days <= -96476615_f64 {
5275        // Consider pulling datetime value from q, not only reverse Rust->q.
5276        // DateTime::signed_duration_since(chrono::MIN_DATETIME, Utc.ymd(2000,1,1).and_hms_nano(0, 0, 0, 0)).num_days())
5277        *qninf::DATETIME
5278    } else if days >= 95015644_f64 {
5279        // Consider pulling datetime value from q, not only reverse Rust->q.
5280        // DateTime::signed_duration_since(chrono::MAX_DATETIME, Utc.ymd(2000,1,1).and_hms_nano(0, 0, 0, 0)).num_days())
5281        *qinf::DATETIME
5282    } else {
5283        Utc.timestamp_millis_opt((ONE_DAY_MILLIS as f64 * (days + KDB_DAY_OFFSET as f64)) as i64)
5284            .unwrap()
5285    }
5286}
5287
5288/// Convert q timespan into `Duration`.
5289pub(crate) fn q_timespan_to_duration(nanos: i64) -> Duration {
5290    Duration::nanoseconds(nanos)
5291}
5292
5293/// Convert q minute into `Duration`.
5294pub(crate) fn q_minute_to_duration(minutes: i32) -> Duration {
5295    Duration::minutes(minutes as i64)
5296}
5297
5298/// Convert q second into `Duration`.
5299pub(crate) fn q_second_to_duration(seconds: i32) -> Duration {
5300    Duration::seconds(seconds as i64)
5301}
5302
5303/// Convert q time into `Duration`.
5304pub(crate) fn q_time_to_duration(millis: i32) -> Duration {
5305    Duration::milliseconds(millis as i64)
5306}
5307
5308//++++++++++++++++++++++++++++++++++++++++++++++++++//
5309// >> Load Modules
5310//++++++++++++++++++++++++++++++++++++++++++++++++++//
5311
5312mod connection;
5313mod deserialize;
5314mod format;
5315mod serialize;
5316// Inject into `ipc` namespace.
5317pub use connection::*;