1use super::*;
6use std::fmt;
7
8impl fmt::Display for K {
15    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16        match self.0.qtype {
17            qtype::ERROR => write!(f, "'{}", self.get_error_string().unwrap()),
18            _ => {
19                let mut stream = String::new();
20                if let Some(precision) = f.precision() {
21                    put_q(self, &mut stream, precision);
22                } else {
23                    put_q(self, &mut stream, 0);
24                }
25                write!(f, "{}", stream)
26            }
27        }
28    }
29}
30
31fn put_bool(boolean: G, stream: &mut String) {
36    stream.push(match boolean {
37        0 => '0',
38        _ => '1',
39    });
40}
41
42fn put_guid(guid: U, stream: &mut String) {
43    let strguid = guid
44        .iter()
45        .map(|byte| format!("{:02x}", byte))
46        .collect::<String>();
47    stream.push_str(
48        format!(
49            "{}-{}-{}-{}-{}",
50            &strguid[0..8],
51            &strguid[8..12],
52            &strguid[12..16],
53            &strguid[16..20],
54            &strguid[20..32]
55        )
56        .as_str(),
57    );
58}
59
60fn put_byte(byte: G, stream: &mut String) {
61    stream.push_str(format!("{:02x}", byte).as_str());
62}
63
64fn put_short(short: H, stream: &mut String) {
65    if short == qnull_base::H {
66        stream.push_str("0N")
67    } else if short == qinf_base::H {
68        stream.push_str("0W")
69    } else if short == qninf_base::H {
70        stream.push_str("-0W")
71    } else {
72        stream.push_str(format!("{}", short).as_str())
73    }
74}
75
76fn put_int(int: I, stream: &mut String) {
77    if int == qnull_base::I {
78        stream.push_str("0N")
79    } else if int == qinf_base::I {
80        stream.push_str("0W")
81    } else if int == qninf_base::I {
82        stream.push_str("-0W")
83    } else {
84        stream.push_str(format!("{}", int).as_str())
85    }
86}
87
88fn put_long(long: J, stream: &mut String) {
89    if long == qnull_base::J {
90        stream.push_str("0N")
91    } else if long == qinf_base::J {
92        stream.push_str("0W")
93    } else if long == qninf_base::J {
94        stream.push_str("-0W")
95    } else {
96        stream.push_str(format!("{}", long).as_str())
97    }
98}
99
100fn put_real(real: E, stream: &mut String, precision: usize) {
101    if real.is_nan() {
102        stream.push_str("0N")
103    } else if real == qinf_base::E {
104        stream.push_str("0W")
105    } else if real == qninf_base::E {
106        stream.push_str("-0W")
107    } else {
108        if precision != 0 {
109            stream.push_str(format!("{1:.*}", precision, real).as_str())
110        } else {
111            stream.push_str(format!("{}", real).as_str())
112        }
113    }
114}
115
116fn put_float(float: F, stream: &mut String, precision: usize) {
117    if float.is_nan() {
118        stream.push_str("0n")
119    } else if float.is_infinite() && float.is_sign_negative() {
120        stream.push_str("-0w")
121    } else if float.is_infinite() {
122        stream.push_str("0w")
123    } else {
124        if precision != 0 {
125            stream.push_str(format!("{1:.*}", precision, float).as_str())
126        } else {
127            stream.push_str(format!("{}", float).as_str())
128        }
129    }
130}
131
132fn put_symbol(symbol: &str, stream: &mut String) {
133    stream.push('`');
134    stream.push_str(symbol);
135}
136
137fn put_timestamp(nanos: J, stream: &mut String) -> bool {
139    if nanos == qnull_base::J {
140        stream.push_str("0N");
141        true
142    } else if nanos == qinf_base::J {
143        stream.push_str("0W");
144        true
145    } else if nanos == qninf_base::J {
146        stream.push_str("-0W");
147        true
148    } else {
149        stream.push_str(
150            q_timestamp_to_datetime(nanos)
151                .format("%Y.%m.%dD%H:%M:%S%.9f")
152                .to_string()
153                .as_str(),
154        );
155        false
156    }
157}
158
159fn put_month(months: I, stream: &mut String) {
160    if months == qnull_base::I {
161        stream.push_str("0N")
162    } else if months == qinf_base::I {
163        stream.push_str("0W")
164    } else if months == qninf_base::I {
165        stream.push_str("-0W")
166    } else {
167        match months.signum() {
168            -1 => {
169                let year = 2000 + months.signum() * (1 + months.abs() / 12);
170                let month = 12 + (1 + months % 12);
171                stream.push_str(format!("{}.{:02}", year, month).as_str())
172            }
173            _ => {
174                stream.push_str(format!("{}.{:02}", 2000 + months / 12, 1 + (months % 12)).as_str())
175            }
176        }
177    }
178}
179
180fn put_date(days: I, stream: &mut String) -> bool {
182    if days == qnull_base::I {
183        stream.push_str("0N");
184        true
185    } else if days == qinf_base::I {
186        stream.push_str("0W");
187        true
188    } else if days == qninf_base::I {
189        stream.push_str("-0W");
190        true
191    } else {
192        stream.push_str(
193            Utc.timestamp_nanos(ONE_DAY_NANOS * (days + KDB_DAY_OFFSET) as i64)
194                .date_naive()
195                .format("%Y.%m.%d")
196                .to_string()
197                .as_str(),
198        );
199        false
200    }
201}
202
203fn put_datetime(days: F, stream: &mut String) -> bool {
205    if days.is_nan() {
206        stream.push_str("0N");
207        true
208    } else if days.is_infinite() && days.is_sign_negative() {
209        stream.push_str("-0W");
210        true
211    } else if days.is_infinite() {
212        stream.push_str("0W");
213        true
214    } else {
215        stream.push_str(
216            q_datetime_to_datetime(days)
217                .format("%Y.%m.%dT%H:%M:%S%.3f")
218                .to_string()
219                .as_str(),
220        );
221        false
222    }
223}
224
225fn put_timespan(nanos: J, stream: &mut String) -> bool {
227    if nanos == qnull_base::J {
228        stream.push_str("0N");
229        true
230    } else if nanos == qinf_base::J {
231        stream.push_str("0W");
232        true
233    } else if nanos == qninf_base::J {
234        stream.push_str("-0W");
235        true
236    } else {
237        let duration = q_timespan_to_duration(nanos);
238        if duration.num_nanoseconds().unwrap() < 0 {
239            stream.push_str(
240                format!(
241                    "-{}D{:02}:{:02}:{:02}.{:09}",
242                    duration.num_days().abs(),
243                    duration.num_hours().abs() % 24,
244                    duration.num_minutes().abs() % 60,
245                    duration.num_seconds().abs() % 60,
246                    duration.num_nanoseconds().unwrap_or_else(|| 0).abs() % 1_000_000_000_i64
247                )
248                .as_str(),
249            );
250        } else {
251            stream.push_str(
252                format!(
253                    "{}D{:02}:{:02}:{:02}.{:09}",
254                    duration.num_days(),
255                    duration.num_hours() % 24,
256                    duration.num_minutes() % 60,
257                    duration.num_seconds() % 60,
258                    duration.num_nanoseconds().unwrap_or_else(|| 0) % 1_000_000_000_i64
259                )
260                .as_str(),
261            );
262        }
263        false
264    }
265}
266
267fn put_minute(minutes: I, stream: &mut String) -> bool {
269    if minutes == qnull_base::I {
270        stream.push_str("0N");
271        true
272    } else if minutes == qinf_base::I {
273        stream.push_str("0W");
274        true
275    } else if minutes == qninf_base::I {
276        stream.push_str("-0W");
277        true
278    } else {
279        let duration = q_minute_to_duration(minutes);
280        if duration.num_minutes() < 0 {
281            stream.push_str(
282                format!(
283                    "-{:02}:{:02}",
284                    duration.num_hours().abs() % 24,
285                    duration.num_minutes().abs() % 60
286                )
287                .as_str(),
288            );
289        } else {
290            stream.push_str(
291                format!(
292                    "{:02}:{:02}",
293                    duration.num_hours() % 24,
294                    duration.num_minutes() % 60
295                )
296                .as_str(),
297            );
298        }
299        false
300    }
301}
302
303fn put_second(seconds: I, stream: &mut String) -> bool {
305    if seconds == qnull_base::I {
306        stream.push_str("0N");
307        true
308    } else if seconds == qinf_base::I {
309        stream.push_str("0W");
310        true
311    } else if seconds == qninf_base::I {
312        stream.push_str("-0W");
313        true
314    } else {
315        let duration = q_second_to_duration(seconds);
316        if duration.num_seconds() < 0 {
317            stream.push_str(
318                format!(
319                    "-{:02}:{:02}:{:02}",
320                    duration.num_hours().abs() % 24,
321                    duration.num_minutes().abs() % 60,
322                    duration.num_seconds().abs() % 60
323                )
324                .as_str(),
325            );
326        } else {
327            stream.push_str(
328                format!(
329                    "{:02}:{:02}:{:02}",
330                    duration.num_hours() % 24,
331                    duration.num_minutes() % 60,
332                    duration.num_seconds() % 60
333                )
334                .as_str(),
335            );
336        }
337        false
338    }
339}
340
341fn put_time(millis: I, stream: &mut String) -> bool {
343    if millis == qnull_base::I {
344        stream.push_str("0N");
345        true
346    } else if millis == qinf_base::I {
347        stream.push_str("0W");
348        true
349    } else if millis == qninf_base::I {
350        stream.push_str("-0W");
351        true
352    } else {
353        let duration = q_time_to_duration(millis);
354        if duration.num_milliseconds() < 0 {
355            stream.push_str(
356                format!(
357                    "-{:02}:{:02}:{:02}.{:03}",
358                    duration.num_hours().abs() % 24,
359                    duration.num_minutes().abs() % 60,
360                    duration.num_seconds().abs() % 60,
361                    duration.num_milliseconds().abs() % 1000_i64
362                )
363                .as_str(),
364            );
365        } else {
366            stream.push_str(
367                format!(
368                    "{:02}:{:02}:{:02}.{:03}",
369                    duration.num_hours() % 24,
370                    duration.num_minutes() % 60,
371                    duration.num_seconds() % 60,
372                    duration.num_milliseconds() % 1000_i64
373                )
374                .as_str(),
375            );
376        }
377        false
378    }
379}
380
381fn put_attribute(attribute: i8, stream: &mut String) {
382    match attribute {
383        qattribute::SORTED => stream.push_str("`s#"),
384        qattribute::PARTED => stream.push_str("`p#"),
385        qattribute::UNIQUE => stream.push_str("`u#"),
386        qattribute::GROUPED => stream.push_str("`g#"),
387        _ => {}
389    }
390}
391
392fn put_bool_list(list: &Vec<G>, stream: &mut String) {
393    let size = list.len();
394    if size == 0 {
395        stream.push_str("`bool$()");
396    } else {
397        if size == 1 {
398            stream.push(',');
399        }
400        list.iter().for_each(|element| {
401            put_bool(*element, stream);
402        });
403        stream.push('b');
404    }
405}
406
407fn put_guid_list(list: &Vec<U>, stream: &mut String) {
408    let size = list.len();
409    if size == 0 {
410        stream.push_str("`guid$()");
411    } else {
412        if size == 1 {
413            stream.push(',');
414        }
415        for i in 0..(size - 1) {
416            put_guid(list[i], stream);
417            stream.push(' ');
418        }
419        put_guid(list[size - 1], stream);
420    }
421}
422
423fn put_byte_list(list: &Vec<G>, stream: &mut String) {
424    let size = list.len();
425    if size == 0 {
426        stream.push_str("`byte$()");
427    } else {
428        if size == 1 {
429            stream.push(',');
430        }
431        stream.push_str("0x");
432        list.iter().for_each(|element| {
433            put_byte(*element, stream);
434        });
435    }
436}
437
438fn put_short_list(list: &Vec<H>, stream: &mut String) {
439    let size = list.len();
440    if size == 0 {
441        stream.push_str("`short$()");
442    } else {
443        if size == 1 {
444            stream.push(',');
445        }
446        for i in 0..(size - 1) {
447            put_short(list[i], stream);
448            stream.push(' ');
449        }
450        put_short(list[size - 1], stream);
451        stream.push('h');
452    }
453}
454
455fn put_int_list(list: &Vec<I>, stream: &mut String) {
456    let size = list.len();
457    if size == 0 {
458        stream.push_str("`int$()");
459    } else {
460        if size == 1 {
461            stream.push(',');
462        }
463        for i in 0..(size - 1) {
464            put_int(list[i], stream);
465            stream.push(' ');
466        }
467        put_int(list[size - 1], stream);
468        stream.push('i');
469    }
470}
471
472fn put_long_list(list: &Vec<J>, stream: &mut String) {
473    let size = list.len();
474    if size == 0 {
475        stream.push_str("`long$()");
476    } else {
477        if size == 1 {
478            stream.push(',');
479        }
480        for i in 0..(size - 1) {
481            put_long(list[i], stream);
482            stream.push(' ');
483        }
484        put_long(list[size - 1], stream);
485    }
486}
487
488fn put_real_list(list: &Vec<E>, stream: &mut String, precision: usize) {
489    let size = list.len();
490    if size == 0 {
491        stream.push_str("`real$()");
492    } else {
493        if size == 1 {
494            stream.push(',');
495        }
496        for i in 0..(size - 1) {
497            put_real(list[i], stream, precision);
498            stream.push(' ');
499        }
500        put_real(list[size - 1], stream, precision);
501        stream.push('e');
502    }
503}
504
505fn put_float_list(list: &Vec<F>, stream: &mut String, precision: usize) {
506    let size = list.len();
507    if size == 0 {
508        stream.push_str("`float$()");
509    } else {
510        if size == 1 {
511            stream.push(',');
512        }
513        for i in 0..(size - 1) {
514            put_float(list[i], stream, precision);
515            stream.push(' ');
516        }
517        put_float(list[size - 1], stream, precision);
518    }
519}
520
521fn put_string(string: &str, stream: &mut String) {
522    let size = string.len();
523    if size == 1 {
524        stream.push(',');
525    }
526    stream.push('"');
527    stream.push_str(string);
528    stream.push('"');
529}
530
531fn put_symbol_list(list: &Vec<S>, stream: &mut String) {
532    let size = list.len();
533    if size == 0 {
534        stream.push_str("`symbol$()");
535    } else {
536        if size == 1 {
537            stream.push(',');
538        }
539        for i in 0..(size - 1) {
540            put_symbol(&list[i], stream);
541        }
542        put_symbol(&list[size - 1], stream);
543    }
544}
545
546fn put_timestamp_list(list: &Vec<J>, stream: &mut String) {
547    let size = list.len();
548    if size == 0 {
549        stream.push_str("`timestamp$()");
550    } else {
551        if size == 1 {
552            stream.push(',');
553        }
554        for i in 0..(size - 1) {
555            put_timestamp(list[i], stream);
556            stream.push(' ');
557        }
558        if put_timestamp(list[size - 1], stream) {
559            stream.push('p');
560        }
561    }
562}
563
564fn put_month_list(list: &Vec<I>, stream: &mut String) {
565    let size = list.len();
566    if size == 0 {
567        stream.push_str("`month$()");
568    } else {
569        if size == 1 {
570            stream.push(',');
571        }
572        for i in 0..(size - 1) {
573            put_month(list[i], stream);
574            stream.push(' ');
575        }
576        put_month(list[size - 1], stream);
577        stream.push('m');
578    }
579}
580
581fn put_date_list(list: &Vec<I>, stream: &mut String) {
582    let size = list.len();
583    if size == 0 {
584        stream.push_str("`date$()");
585    } else {
586        if size == 1 {
587            stream.push(',');
588        }
589        for i in 0..(size - 1) {
590            put_date(list[i], stream);
591            stream.push(' ');
592        }
593        if put_date(list[size - 1], stream) {
594            stream.push('d');
595        }
596    }
597}
598
599fn put_datetime_list(list: &Vec<F>, stream: &mut String) {
600    let size = list.len();
601    if size == 0 {
602        stream.push_str("`datetime$()");
603    } else {
604        if size == 1 {
605            stream.push(',');
606        }
607        for i in 0..(size - 1) {
608            put_datetime(list[i], stream);
609            stream.push(' ');
610        }
611        if put_datetime(list[size - 1], stream) {
612            stream.push('z');
613        }
614    }
615}
616
617fn put_timespan_list(list: &Vec<J>, stream: &mut String) {
618    let size = list.len();
619    if size == 0 {
620        stream.push_str("`timespan$()");
621    } else {
622        if size == 1 {
623            stream.push(',');
624        }
625        for i in 0..(size - 1) {
626            put_timespan(list[i], stream);
627            stream.push(' ');
628        }
629        if put_timespan(list[size - 1], stream) {
630            stream.push('n');
631        }
632    }
633}
634
635fn put_minute_list(list: &Vec<I>, stream: &mut String) {
636    let size = list.len();
637    if size == 0 {
638        stream.push_str("`minute$()");
639    } else {
640        if size == 1 {
641            stream.push(',');
642        }
643        for i in 0..(size - 1) {
644            put_minute(list[i], stream);
645            stream.push(' ');
646        }
647        if put_minute(list[size - 1], stream) {
648            stream.push('u');
649        }
650    }
651}
652
653fn put_second_list(list: &Vec<I>, stream: &mut String) {
654    let size = list.len();
655    if size == 0 {
656        stream.push_str("`second$()");
657    } else {
658        if size == 1 {
659            stream.push(',');
660        }
661        for i in 0..(size - 1) {
662            put_second(list[i], stream);
663            stream.push(' ');
664        }
665        if put_second(list[size - 1], stream) {
666            stream.push('v');
667        }
668    }
669}
670
671fn put_time_list(list: &Vec<I>, stream: &mut String) {
672    let size = list.len();
673    if size == 0 {
674        stream.push_str("`time$()");
675    } else {
676        if size == 1 {
677            stream.push(',');
678        }
679        for i in 0..(size - 1) {
680            put_time(list[i], stream);
681            stream.push(' ');
682        }
683        if put_time(list[size - 1], stream) {
684            stream.push('t');
685        }
686    }
687}
688
689fn put_compound_list(list: &Vec<K>, stream: &mut String, precision: usize) {
690    let size = list.len();
691    if size == 0 {
692        stream.push_str("()");
693    } else {
694        if size == 1 {
695            stream.push(',');
696            put_q(&list[0], stream, precision);
697        } else {
698            stream.push('(');
699            for i in 0..(size - 1) {
700                put_q(&list[i], stream, precision);
701                stream.push(';');
702            }
703            put_q(&list[size - 1], stream, precision);
704            stream.push(')');
705        }
706    }
707}
708
709fn put_table(table: &K, stream: &mut String, precision: usize) {
710    stream.push('+');
711    put_dictionary(table.get_dictionary().unwrap(), stream, precision);
712}
713
714fn put_dictionary(dictionary: &K, stream: &mut String, precision: usize) {
715    let dictionary_ = dictionary.as_vec::<K>().unwrap();
716    let is_keyed_table = dictionary_[0].get_type() == qtype::TABLE;
717    if is_keyed_table {
718        stream.push('(');
719    }
720    put_q(&dictionary_[0], stream, precision);
721    if is_keyed_table {
722        stream.push(')');
723    }
724    stream.push('!');
725    if is_keyed_table {
726        stream.push('(');
727    }
728    put_q(&dictionary_[1], stream, precision);
729    if is_keyed_table {
730        stream.push(')');
731    }
732}
733
734fn put_q(object: &K, stream: &mut String, precision: usize) {
735    match object.0.qtype {
736        qtype::BOOL_ATOM => {
737            put_bool(object.get_byte().unwrap(), stream);
738            stream.push('b');
739        }
740        qtype::GUID_ATOM => put_guid(object.get_guid().unwrap(), stream),
741        qtype::BYTE_ATOM => {
742            stream.push_str("0x");
743            put_byte(object.get_byte().unwrap(), stream);
744        }
745        qtype::SHORT_ATOM => {
746            put_short(object.get_short().unwrap(), stream);
747            stream.push('h');
748        }
749        qtype::INT_ATOM => {
750            put_int(object.get_int().unwrap(), stream);
751            stream.push('i');
752        }
753        qtype::LONG_ATOM => put_long(object.get_long().unwrap(), stream),
754        qtype::REAL_ATOM => {
755            put_real(object.get_real().unwrap(), stream, precision);
756            stream.push('e');
757        }
758        qtype::FLOAT_ATOM => put_float(object.get_float().unwrap(), stream, precision),
759        qtype::CHAR => {
760            stream.push('"');
761            stream.push(object.get_char().unwrap());
762            stream.push('"');
763        }
764        qtype::SYMBOL_ATOM => put_symbol(object.get_symbol().unwrap(), stream),
765        qtype::TIMESTAMP_ATOM => {
766            if put_timestamp(object.get_long().unwrap(), stream) {
767                stream.push('p');
768            }
769        }
770        qtype::MONTH_ATOM => {
771            put_month(object.get_int().unwrap(), stream);
772            stream.push('m');
773        }
774        qtype::DATE_ATOM => {
775            if put_date(object.get_int().unwrap(), stream) {
776                stream.push('d');
777            }
778        }
779        qtype::DATETIME_ATOM => {
780            if put_datetime(object.get_float().unwrap(), stream) {
781                stream.push('z');
782            }
783        }
784        qtype::TIMESPAN_ATOM => {
785            if put_timespan(object.get_long().unwrap(), stream) {
786                stream.push('n');
787            }
788        }
789        qtype::MINUTE_ATOM => {
790            if put_minute(object.get_int().unwrap(), stream) {
791                stream.push('u');
792            }
793        }
794        qtype::SECOND_ATOM => {
795            if put_second(object.get_int().unwrap(), stream) {
796                stream.push('v');
797            }
798        }
799        qtype::TIME_ATOM => {
800            if put_time(object.get_int().unwrap(), stream) {
801                stream.push('t');
802            }
803        }
804        qtype::COMPOUND_LIST => {
805            put_attribute(object.0.attribute, stream);
807            put_compound_list(object.as_vec::<K>().unwrap(), stream, precision)
808        }
809        qtype::BOOL_LIST => {
810            put_attribute(object.0.attribute, stream);
812            put_bool_list(object.as_vec::<G>().unwrap(), stream)
813        }
814        qtype::GUID_LIST => {
815            put_attribute(object.0.attribute, stream);
817            put_guid_list(object.as_vec::<U>().unwrap(), stream)
818        }
819        qtype::BYTE_LIST => {
820            put_attribute(object.0.attribute, stream);
822            put_byte_list(object.as_vec::<G>().unwrap(), stream)
823        }
824        qtype::SHORT_LIST => {
825            put_attribute(object.0.attribute, stream);
827            put_short_list(object.as_vec::<H>().unwrap(), stream)
828        }
829        qtype::INT_LIST => {
830            put_attribute(object.0.attribute, stream);
832            put_int_list(object.as_vec::<I>().unwrap(), stream)
833        }
834        qtype::LONG_LIST => {
835            put_attribute(object.0.attribute, stream);
837            put_long_list(object.as_vec::<J>().unwrap(), stream)
838        }
839        qtype::REAL_LIST => {
840            put_attribute(object.0.attribute, stream);
842            put_real_list(object.as_vec::<E>().unwrap(), stream, precision)
843        }
844        qtype::FLOAT_LIST => {
845            put_attribute(object.0.attribute, stream);
847            put_float_list(object.as_vec::<F>().unwrap(), stream, precision)
848        }
849        qtype::STRING => {
850            put_attribute(object.0.attribute, stream);
852            put_string(object.as_string().unwrap(), stream)
853        }
854        qtype::SYMBOL_LIST => {
855            put_attribute(object.0.attribute, stream);
857            put_symbol_list(object.as_vec::<S>().unwrap(), stream)
858        }
859        qtype::TIMESTAMP_LIST => {
860            put_attribute(object.0.attribute, stream);
862            put_timestamp_list(object.as_vec::<J>().unwrap(), stream)
863        }
864        qtype::MONTH_LIST => {
865            put_attribute(object.0.attribute, stream);
867            put_month_list(object.as_vec::<I>().unwrap(), stream)
868        }
869        qtype::DATE_LIST => {
870            put_attribute(object.0.attribute, stream);
872            put_date_list(object.as_vec::<I>().unwrap(), stream)
873        }
874        qtype::DATETIME_LIST => {
875            put_attribute(object.0.attribute, stream);
877            put_datetime_list(object.as_vec::<F>().unwrap(), stream)
878        }
879        qtype::TIMESPAN_LIST => {
880            put_attribute(object.0.attribute, stream);
882            put_timespan_list(object.as_vec::<J>().unwrap(), stream)
883        }
884        qtype::MINUTE_LIST => {
885            put_attribute(object.0.attribute, stream);
887            put_minute_list(object.as_vec::<I>().unwrap(), stream)
888        }
889        qtype::SECOND_LIST => {
890            put_attribute(object.0.attribute, stream);
892            put_second_list(object.as_vec::<I>().unwrap(), stream)
893        }
894        qtype::TIME_LIST => {
895            put_attribute(object.0.attribute, stream);
897            put_time_list(object.as_vec::<I>().unwrap(), stream)
898        }
899        qtype::TABLE => put_table(object, stream, precision),
900        qtype::DICTIONARY | qtype::SORTED_DICTIONARY => put_dictionary(object, stream, precision),
901        qtype::NULL => stream.push_str("::"),
902        _ => unimplemented!(),
903    }
904}