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::*;