Skip to main content

iceberg/spec/values/
literal.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Literal values in Iceberg
19
20use std::any::Any;
21use std::str::FromStr;
22
23use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
24use ordered_float::OrderedFloat;
25use serde_json::{Map as JsonMap, Number, Value as JsonValue};
26use uuid::Uuid;
27
28use super::Map;
29use super::decimal_utils::{
30    decimal_from_str_exact, decimal_mantissa, decimal_rescale, try_decimal_from_i128_with_scale,
31};
32use super::primitive::PrimitiveLiteral;
33use super::struct_value::Struct;
34use super::temporal::{date, time, timestamp, timestamptz};
35use crate::error::Result;
36use crate::spec::datatypes::{PrimitiveType, Type};
37use crate::{Error, ErrorKind};
38
39/// Values present in iceberg type
40#[derive(Clone, Debug, PartialEq, Eq, Hash)]
41pub enum Literal {
42    /// A primitive value
43    Primitive(PrimitiveLiteral),
44    /// A struct is a tuple of typed values. Each field in the tuple is named and has an integer id that is unique in the table schema.
45    /// Each field can be either optional or required, meaning that values can (or cannot) be null. Fields may be any type.
46    /// Fields may have an optional comment or doc string. Fields can have default values.
47    Struct(Struct),
48    /// A list is a collection of values with some element type.
49    /// The element field has an integer id that is unique in the table schema.
50    /// Elements can be either optional or required. Element types may be any type.
51    List(Vec<Option<Literal>>),
52    /// A map is a collection of key-value pairs with a key type and a value type.
53    /// Both the key field and value field each have an integer id that is unique in the table schema.
54    /// Map keys are required and map values can be either optional or required. Both map keys and map values may be any type, including nested types.
55    Map(Map),
56}
57
58impl Literal {
59    /// Creates a boolean value.
60    ///
61    /// Example:
62    /// ```rust
63    /// use iceberg::spec::{Literal, PrimitiveLiteral};
64    /// let t = Literal::bool(true);
65    ///
66    /// assert_eq!(Literal::Primitive(PrimitiveLiteral::Boolean(true)), t);
67    /// ```
68    pub fn bool<T: Into<bool>>(t: T) -> Self {
69        Self::Primitive(PrimitiveLiteral::Boolean(t.into()))
70    }
71
72    /// Creates a boolean value from string.
73    /// See [Parse bool from str](https://doc.rust-lang.org/stable/std/primitive.bool.html#impl-FromStr-for-bool) for reference.
74    ///
75    /// Example:
76    /// ```rust
77    /// use iceberg::spec::{Literal, PrimitiveLiteral};
78    /// let t = Literal::bool_from_str("false").unwrap();
79    ///
80    /// assert_eq!(Literal::Primitive(PrimitiveLiteral::Boolean(false)), t);
81    /// ```
82    pub fn bool_from_str<S: AsRef<str>>(s: S) -> Result<Self> {
83        let v = s.as_ref().parse::<bool>().map_err(|e| {
84            Error::new(ErrorKind::DataInvalid, "Can't parse string to bool.").with_source(e)
85        })?;
86        Ok(Self::Primitive(PrimitiveLiteral::Boolean(v)))
87    }
88
89    /// Creates an 32bit integer.
90    ///
91    /// Example:
92    /// ```rust
93    /// use iceberg::spec::{Literal, PrimitiveLiteral};
94    /// let t = Literal::int(23i8);
95    ///
96    /// assert_eq!(Literal::Primitive(PrimitiveLiteral::Int(23)), t);
97    /// ```
98    pub fn int<T: Into<i32>>(t: T) -> Self {
99        Self::Primitive(PrimitiveLiteral::Int(t.into()))
100    }
101
102    /// Creates an 64bit integer.
103    ///
104    /// Example:
105    /// ```rust
106    /// use iceberg::spec::{Literal, PrimitiveLiteral};
107    /// let t = Literal::long(24i8);
108    ///
109    /// assert_eq!(Literal::Primitive(PrimitiveLiteral::Long(24)), t);
110    /// ```
111    pub fn long<T: Into<i64>>(t: T) -> Self {
112        Self::Primitive(PrimitiveLiteral::Long(t.into()))
113    }
114
115    /// Creates an 32bit floating point number.
116    ///
117    /// Example:
118    /// ```rust
119    /// use iceberg::spec::{Literal, PrimitiveLiteral};
120    /// use ordered_float::OrderedFloat;
121    /// let t = Literal::float(32.1f32);
122    ///
123    /// assert_eq!(
124    ///     Literal::Primitive(PrimitiveLiteral::Float(OrderedFloat(32.1))),
125    ///     t
126    /// );
127    /// ```
128    pub fn float<T: Into<f32>>(t: T) -> Self {
129        Self::Primitive(PrimitiveLiteral::Float(OrderedFloat(t.into())))
130    }
131
132    /// Creates an 32bit floating point number.
133    ///
134    /// Example:
135    /// ```rust
136    /// use iceberg::spec::{Literal, PrimitiveLiteral};
137    /// use ordered_float::OrderedFloat;
138    /// let t = Literal::double(32.1f64);
139    ///
140    /// assert_eq!(
141    ///     Literal::Primitive(PrimitiveLiteral::Double(OrderedFloat(32.1))),
142    ///     t
143    /// );
144    /// ```
145    pub fn double<T: Into<f64>>(t: T) -> Self {
146        Self::Primitive(PrimitiveLiteral::Double(OrderedFloat(t.into())))
147    }
148
149    /// Creates date literal from number of days from unix epoch directly.
150    pub fn date(days: i32) -> Self {
151        Self::Primitive(PrimitiveLiteral::Int(days))
152    }
153
154    /// Creates a date in `%Y-%m-%d` format, assume in utc timezone.
155    ///
156    /// See [`NaiveDate::from_str`].
157    ///
158    /// Example
159    /// ```rust
160    /// use iceberg::spec::Literal;
161    /// let t = Literal::date_from_str("1970-01-03").unwrap();
162    ///
163    /// assert_eq!(Literal::date(2), t);
164    /// ```
165    pub fn date_from_str<S: AsRef<str>>(s: S) -> Result<Self> {
166        let t = s.as_ref().parse::<NaiveDate>().map_err(|e| {
167            Error::new(
168                ErrorKind::DataInvalid,
169                format!("Can't parse date from string: {}", s.as_ref()),
170            )
171            .with_source(e)
172        })?;
173
174        Ok(Self::date(date::date_from_naive_date(t)))
175    }
176
177    /// Create a date from calendar date (year, month and day).
178    ///
179    /// See [`NaiveDate::from_ymd_opt`].
180    ///
181    /// Example:
182    ///
183    ///```rust
184    /// use iceberg::spec::Literal;
185    /// let t = Literal::date_from_ymd(1970, 1, 5).unwrap();
186    ///
187    /// assert_eq!(Literal::date(4), t);
188    /// ```
189    pub fn date_from_ymd(year: i32, month: u32, day: u32) -> Result<Self> {
190        let t = NaiveDate::from_ymd_opt(year, month, day).ok_or_else(|| {
191            Error::new(
192                ErrorKind::DataInvalid,
193                format!("Can't create date from year: {year}, month: {month}, day: {day}"),
194            )
195        })?;
196
197        Ok(Self::date(date::date_from_naive_date(t)))
198    }
199
200    /// Creates time in microseconds directly
201    pub fn time(value: i64) -> Self {
202        Self::Primitive(PrimitiveLiteral::Long(value))
203    }
204
205    /// Creates time literal from [`chrono::NaiveTime`].
206    fn time_from_naive_time(t: NaiveTime) -> Self {
207        let duration = t - date::unix_epoch().time();
208        // It's safe to unwrap here since less than 24 hours will never overflow.
209        let micro_secs = duration.num_microseconds().unwrap();
210
211        Literal::time(micro_secs)
212    }
213
214    /// Creates time in microseconds in `%H:%M:%S:.f` format.
215    ///
216    /// See [`NaiveTime::from_str`] for details.
217    ///
218    /// Example:
219    /// ```rust
220    /// use iceberg::spec::Literal;
221    /// let t = Literal::time_from_str("01:02:01.888999777").unwrap();
222    ///
223    /// let micro_secs = {
224    ///     1 * 3600 * 1_000_000 + // 1 hour
225    ///     2 * 60 * 1_000_000 +   // 2 minutes
226    ///     1 * 1_000_000 + // 1 second
227    ///     888999 // microseconds
228    /// };
229    /// assert_eq!(Literal::time(micro_secs), t);
230    /// ```
231    pub fn time_from_str<S: AsRef<str>>(s: S) -> Result<Self> {
232        let t = s.as_ref().parse::<NaiveTime>().map_err(|e| {
233            Error::new(
234                ErrorKind::DataInvalid,
235                format!("Can't parse time from string: {}", s.as_ref()),
236            )
237            .with_source(e)
238        })?;
239
240        Ok(Self::time_from_naive_time(t))
241    }
242
243    /// Creates time literal from hour, minute, second, and microseconds.
244    ///
245    /// See [`NaiveTime::from_hms_micro_opt`].
246    ///
247    /// Example:
248    /// ```rust
249    /// use iceberg::spec::Literal;
250    /// let t = Literal::time_from_hms_micro(22, 15, 33, 111).unwrap();
251    ///
252    /// assert_eq!(Literal::time_from_str("22:15:33.000111").unwrap(), t);
253    /// ```
254    pub fn time_from_hms_micro(hour: u32, min: u32, sec: u32, micro: u32) -> Result<Self> {
255        let t = NaiveTime::from_hms_micro_opt(hour, min, sec, micro)
256            .ok_or_else(|| Error::new(
257                ErrorKind::DataInvalid,
258                format!("Can't create time from hour: {hour}, min: {min}, second: {sec}, microsecond: {micro}"),
259            ))?;
260        Ok(Self::time_from_naive_time(t))
261    }
262
263    /// Creates a timestamp from unix epoch in microseconds.
264    pub fn timestamp(value: i64) -> Self {
265        Self::Primitive(PrimitiveLiteral::Long(value))
266    }
267
268    /// Creates a timestamp with timezone from unix epoch in microseconds.
269    pub fn timestamptz(value: i64) -> Self {
270        Self::Primitive(PrimitiveLiteral::Long(value))
271    }
272
273    /// Creates a timestamp from unix epoch in nanoseconds.
274    pub(crate) fn timestamp_nano(value: i64) -> Self {
275        Self::Primitive(PrimitiveLiteral::Long(value))
276    }
277
278    /// Creates a timestamp with timezone from unix epoch in nanoseconds.
279    pub(crate) fn timestamptz_nano(value: i64) -> Self {
280        Self::Primitive(PrimitiveLiteral::Long(value))
281    }
282
283    /// Creates a timestamp from [`DateTime`].
284    pub fn timestamp_from_datetime<T: TimeZone>(dt: DateTime<T>) -> Self {
285        Self::timestamp(dt.with_timezone(&Utc).timestamp_micros())
286    }
287
288    /// Creates a timestamp with timezone from [`DateTime`].
289    pub fn timestamptz_from_datetime<T: TimeZone>(dt: DateTime<T>) -> Self {
290        Self::timestamptz(dt.with_timezone(&Utc).timestamp_micros())
291    }
292
293    /// Parse a timestamp in RFC3339 format.
294    ///
295    /// See [`DateTime<Utc>::from_str`].
296    ///
297    /// Example:
298    ///
299    /// ```rust
300    /// use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime};
301    /// use iceberg::spec::Literal;
302    /// let t = Literal::timestamp_from_str("2012-12-12 12:12:12.8899-04:00").unwrap();
303    ///
304    /// let t2 = {
305    ///     let date = NaiveDate::from_ymd_opt(2012, 12, 12).unwrap();
306    ///     let time = NaiveTime::from_hms_micro_opt(12, 12, 12, 889900).unwrap();
307    ///     let dt = NaiveDateTime::new(date, time);
308    ///     Literal::timestamp_from_datetime(DateTime::<FixedOffset>::from_local(
309    ///         dt,
310    ///         FixedOffset::west_opt(4 * 3600).unwrap(),
311    ///     ))
312    /// };
313    ///
314    /// assert_eq!(t, t2);
315    /// ```
316    pub fn timestamp_from_str<S: AsRef<str>>(s: S) -> Result<Self> {
317        let dt = DateTime::<Utc>::from_str(s.as_ref()).map_err(|e| {
318            Error::new(ErrorKind::DataInvalid, "Can't parse datetime.").with_source(e)
319        })?;
320
321        Ok(Self::timestamp_from_datetime(dt))
322    }
323
324    /// Similar to [`Literal::timestamp_from_str`], but return timestamp with timezone literal.
325    pub fn timestamptz_from_str<S: AsRef<str>>(s: S) -> Result<Self> {
326        let dt = DateTime::<Utc>::from_str(s.as_ref()).map_err(|e| {
327            Error::new(ErrorKind::DataInvalid, "Can't parse datetime.").with_source(e)
328        })?;
329
330        Ok(Self::timestamptz_from_datetime(dt))
331    }
332
333    /// Creates a string literal.
334    pub fn string<S: ToString>(s: S) -> Self {
335        Self::Primitive(PrimitiveLiteral::String(s.to_string()))
336    }
337
338    /// Creates uuid literal.
339    pub fn uuid(uuid: Uuid) -> Self {
340        Self::Primitive(PrimitiveLiteral::UInt128(uuid.as_u128()))
341    }
342
343    /// Creates uuid from str. See [`Uuid::parse_str`].
344    ///
345    /// Example:
346    ///
347    /// ```rust
348    /// use iceberg::spec::Literal;
349    /// use uuid::Uuid;
350    /// let t1 = Literal::uuid_from_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8").unwrap();
351    /// let t2 = Literal::uuid(Uuid::from_u128_le(0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1));
352    ///
353    /// assert_eq!(t1, t2);
354    /// ```
355    pub fn uuid_from_str<S: AsRef<str>>(s: S) -> Result<Self> {
356        let uuid = Uuid::parse_str(s.as_ref()).map_err(|e| {
357            Error::new(
358                ErrorKind::DataInvalid,
359                format!("Can't parse uuid from string: {}", s.as_ref()),
360            )
361            .with_source(e)
362        })?;
363        Ok(Self::uuid(uuid))
364    }
365
366    /// Creates a fixed literal from bytes.
367    ///
368    /// Example:
369    ///
370    /// ```rust
371    /// use iceberg::spec::{Literal, PrimitiveLiteral};
372    /// let t1 = Literal::fixed(vec![1u8, 2u8]);
373    /// let t2 = Literal::Primitive(PrimitiveLiteral::Binary(vec![1u8, 2u8]));
374    ///
375    /// assert_eq!(t1, t2);
376    /// ```
377    pub fn fixed<I: IntoIterator<Item = u8>>(input: I) -> Self {
378        Literal::Primitive(PrimitiveLiteral::Binary(input.into_iter().collect()))
379    }
380
381    /// Creates a binary literal from bytes.
382    ///
383    /// Example:
384    ///
385    /// ```rust
386    /// use iceberg::spec::{Literal, PrimitiveLiteral};
387    /// let t1 = Literal::binary(vec![1u8, 2u8]);
388    /// let t2 = Literal::Primitive(PrimitiveLiteral::Binary(vec![1u8, 2u8]));
389    ///
390    /// assert_eq!(t1, t2);
391    /// ```
392    pub fn binary<I: IntoIterator<Item = u8>>(input: I) -> Self {
393        Literal::Primitive(PrimitiveLiteral::Binary(input.into_iter().collect()))
394    }
395
396    /// Creates a decimal literal.
397    pub fn decimal(decimal: i128) -> Self {
398        Self::Primitive(PrimitiveLiteral::Int128(decimal))
399    }
400
401    /// Creates decimal literal from string.
402    ///
403    /// Example:
404    ///
405    /// ```rust
406    /// use iceberg::spec::Literal;
407    /// let t1 = Literal::decimal(12345);
408    /// let t2 = Literal::decimal_from_str("123.45").unwrap();
409    ///
410    /// assert_eq!(t1, t2);
411    /// ```
412    pub fn decimal_from_str<S: AsRef<str>>(s: S) -> Result<Self> {
413        let decimal = decimal_from_str_exact(s.as_ref())?;
414        Ok(Self::decimal(decimal_mantissa(&decimal)))
415    }
416
417    /// Attempts to convert the Literal to a PrimitiveLiteral
418    pub fn as_primitive_literal(&self) -> Option<PrimitiveLiteral> {
419        match self {
420            Literal::Primitive(primitive) => Some(primitive.clone()),
421            _ => None,
422        }
423    }
424
425    /// Create iceberg value from a json value
426    ///
427    /// See [this spec](https://iceberg.apache.org/spec/#json-single-value-serialization) for reference.
428    pub fn try_from_json(value: JsonValue, data_type: &Type) -> Result<Option<Self>> {
429        match data_type {
430            Type::Primitive(primitive) => match (primitive, value) {
431                (PrimitiveType::Boolean, JsonValue::Bool(bool)) => {
432                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Boolean(bool))))
433                }
434                (PrimitiveType::Int, JsonValue::Number(number)) => {
435                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Int(
436                        number
437                            .as_i64()
438                            .ok_or(Error::new(
439                                ErrorKind::DataInvalid,
440                                "Failed to convert json number to int",
441                            ))?
442                            .try_into()?,
443                    ))))
444                }
445                (PrimitiveType::Long, JsonValue::Number(number)) => Ok(Some(Literal::Primitive(
446                    PrimitiveLiteral::Long(number.as_i64().ok_or(Error::new(
447                        ErrorKind::DataInvalid,
448                        "Failed to convert json number to long",
449                    ))?),
450                ))),
451                (PrimitiveType::Float, JsonValue::Number(number)) => Ok(Some(Literal::Primitive(
452                    PrimitiveLiteral::Float(OrderedFloat(number.as_f64().ok_or(Error::new(
453                        ErrorKind::DataInvalid,
454                        "Failed to convert json number to float",
455                    ))? as f32)),
456                ))),
457                (PrimitiveType::Double, JsonValue::Number(number)) => Ok(Some(Literal::Primitive(
458                    PrimitiveLiteral::Double(OrderedFloat(number.as_f64().ok_or(Error::new(
459                        ErrorKind::DataInvalid,
460                        "Failed to convert json number to double",
461                    ))?)),
462                ))),
463                (PrimitiveType::Date, JsonValue::String(s)) => {
464                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Int(
465                        date::date_to_days(&NaiveDate::parse_from_str(&s, "%Y-%m-%d")?),
466                    ))))
467                }
468                (PrimitiveType::Date, JsonValue::Number(number)) => {
469                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Int(
470                        number
471                            .as_i64()
472                            .ok_or(Error::new(
473                                ErrorKind::DataInvalid,
474                                "Failed to convert json number to date (days since epoch)",
475                            ))?
476                            .try_into()?,
477                    ))))
478                }
479                (PrimitiveType::Time, JsonValue::String(s)) => {
480                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Long(
481                        time::time_to_microseconds(&NaiveTime::parse_from_str(&s, "%H:%M:%S%.f")?),
482                    ))))
483                }
484                (PrimitiveType::Timestamp, JsonValue::String(s)) => Ok(Some(Literal::Primitive(
485                    PrimitiveLiteral::Long(timestamp::datetime_to_microseconds(
486                        &NaiveDateTime::parse_from_str(&s, "%Y-%m-%dT%H:%M:%S%.f")?,
487                    )),
488                ))),
489                (PrimitiveType::Timestamptz, JsonValue::String(s)) => {
490                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Long(
491                        timestamptz::datetimetz_to_microseconds(&Utc.from_utc_datetime(
492                            &NaiveDateTime::parse_from_str(&s, "%Y-%m-%dT%H:%M:%S%.f+00:00")?,
493                        )),
494                    ))))
495                }
496                (PrimitiveType::TimestampNs, JsonValue::String(s)) => {
497                    let ndt = NaiveDateTime::parse_from_str(&s, "%Y-%m-%dT%H:%M:%S%.f")?;
498                    let nanos = timestamp::datetime_to_nanoseconds(&ndt).ok_or_else(|| {
499                        Error::new(
500                            ErrorKind::DataInvalid,
501                            format!(
502                                "Timestamp is outside the representable nanosecond range: {ndt}"
503                            ),
504                        )
505                    })?;
506                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Long(nanos))))
507                }
508                (PrimitiveType::TimestamptzNs, JsonValue::String(s)) => {
509                    let dt = Utc.from_utc_datetime(&NaiveDateTime::parse_from_str(
510                        &s,
511                        "%Y-%m-%dT%H:%M:%S%.f+00:00",
512                    )?);
513                    let nanos = timestamptz::datetimetz_to_nanoseconds(&dt).ok_or_else(|| {
514                        Error::new(
515                            ErrorKind::DataInvalid,
516                            format!(
517                                "Timestamptz is outside the representable nanosecond range: {dt}"
518                            ),
519                        )
520                    })?;
521                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Long(nanos))))
522                }
523                (PrimitiveType::String, JsonValue::String(s)) => {
524                    Ok(Some(Literal::Primitive(PrimitiveLiteral::String(s))))
525                }
526                (PrimitiveType::Uuid, JsonValue::String(s)) => Ok(Some(Literal::Primitive(
527                    PrimitiveLiteral::UInt128(Uuid::parse_str(&s)?.as_u128()),
528                ))),
529                (PrimitiveType::Fixed(size), JsonValue::String(s)) => {
530                    let bytes = decode_hex_bytes(&s)?;
531                    validate_fixed_size(bytes.len(), *size)?;
532                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Binary(bytes))))
533                }
534                (PrimitiveType::Binary, JsonValue::String(s)) => Ok(Some(Literal::Primitive(
535                    PrimitiveLiteral::Binary(decode_hex_bytes(&s)?),
536                ))),
537                (
538                    PrimitiveType::Decimal {
539                        precision: _,
540                        scale,
541                    },
542                    JsonValue::String(s),
543                ) => {
544                    let decimal = decimal_from_str_exact(&s)?;
545                    let rescaled = decimal_rescale(decimal, *scale);
546                    Ok(Some(Literal::Primitive(PrimitiveLiteral::Int128(
547                        decimal_mantissa(&rescaled),
548                    ))))
549                }
550                (_, JsonValue::Null) => Ok(None),
551                (i, j) => Err(Error::new(
552                    ErrorKind::DataInvalid,
553                    format!("The json value {j} doesn't fit to the iceberg type {i}."),
554                )),
555            },
556            Type::Struct(schema) => {
557                if let JsonValue::Object(mut object) = value {
558                    Ok(Some(Literal::Struct(Struct::from_iter(
559                        schema.fields().iter().map(|field| {
560                            object.remove(&field.id.to_string()).and_then(|value| {
561                                Literal::try_from_json(value, &field.field_type)
562                                    .and_then(|value| {
563                                        value.ok_or(Error::new(
564                                            ErrorKind::DataInvalid,
565                                            "Key of map cannot be null",
566                                        ))
567                                    })
568                                    .ok()
569                            })
570                        }),
571                    ))))
572                } else {
573                    Err(Error::new(
574                        ErrorKind::DataInvalid,
575                        "The json value for a struct type must be an object.",
576                    ))
577                }
578            }
579            Type::List(list) => {
580                if let JsonValue::Array(array) = value {
581                    Ok(Some(Literal::List(
582                        array
583                            .into_iter()
584                            .map(|value| {
585                                Literal::try_from_json(value, &list.element_field.field_type)
586                            })
587                            .collect::<Result<Vec<_>>>()?,
588                    )))
589                } else {
590                    Err(Error::new(
591                        ErrorKind::DataInvalid,
592                        "The json value for a list type must be an array.",
593                    ))
594                }
595            }
596            Type::Map(map) => {
597                if let JsonValue::Object(mut object) = value {
598                    if let (Some(JsonValue::Array(keys)), Some(JsonValue::Array(values))) =
599                        (object.remove("keys"), object.remove("values"))
600                    {
601                        Ok(Some(Literal::Map(Map::from_iter(
602                            keys.into_iter()
603                                .zip(values)
604                                .map(|(key, value)| {
605                                    Ok((
606                                        Literal::try_from_json(key, &map.key_field.field_type)
607                                            .and_then(|value| {
608                                                value.ok_or(Error::new(
609                                                    ErrorKind::DataInvalid,
610                                                    "Key of map cannot be null",
611                                                ))
612                                            })?,
613                                        Literal::try_from_json(value, &map.value_field.field_type)?,
614                                    ))
615                                })
616                                .collect::<Result<Vec<_>>>()?,
617                        ))))
618                    } else {
619                        Err(Error::new(
620                            ErrorKind::DataInvalid,
621                            "The json value for a list type must be an array.",
622                        ))
623                    }
624                } else {
625                    Err(Error::new(
626                        ErrorKind::DataInvalid,
627                        "The json value for a list type must be an array.",
628                    ))
629                }
630            }
631            Type::Variant(_) => Err(Error::new(
632                ErrorKind::DataInvalid,
633                "Variant type is not supported for single-value JSON serialization",
634            )),
635        }
636    }
637
638    /// Converting iceberg value to json value.
639    ///
640    /// See [this spec](https://iceberg.apache.org/spec/#json-single-value-serialization) for reference.
641    pub fn try_into_json(self, r#type: &Type) -> Result<JsonValue> {
642        match (self, r#type) {
643            (Literal::Primitive(prim), Type::Primitive(prim_type)) => match (prim_type, prim) {
644                (PrimitiveType::Boolean, PrimitiveLiteral::Boolean(val)) => {
645                    Ok(JsonValue::Bool(val))
646                }
647                (PrimitiveType::Int, PrimitiveLiteral::Int(val)) => {
648                    Ok(JsonValue::Number((val).into()))
649                }
650                (PrimitiveType::Long, PrimitiveLiteral::Long(val)) => {
651                    Ok(JsonValue::Number((val).into()))
652                }
653                (PrimitiveType::Float, PrimitiveLiteral::Float(val)) => {
654                    match Number::from_f64(val.0 as f64) {
655                        Some(number) => Ok(JsonValue::Number(number)),
656                        None => Ok(JsonValue::Null),
657                    }
658                }
659                (PrimitiveType::Double, PrimitiveLiteral::Double(val)) => {
660                    match Number::from_f64(val.0) {
661                        Some(number) => Ok(JsonValue::Number(number)),
662                        None => Ok(JsonValue::Null),
663                    }
664                }
665                (PrimitiveType::Date, PrimitiveLiteral::Int(val)) => {
666                    Ok(JsonValue::String(date::days_to_date(val).to_string()))
667                }
668                (PrimitiveType::Time, PrimitiveLiteral::Long(val)) => Ok(JsonValue::String(
669                    time::microseconds_to_time(val).to_string(),
670                )),
671                (PrimitiveType::Timestamp, PrimitiveLiteral::Long(val)) => Ok(JsonValue::String(
672                    timestamp::microseconds_to_datetime(val)
673                        .format("%Y-%m-%dT%H:%M:%S%.f")
674                        .to_string(),
675                )),
676                (PrimitiveType::Timestamptz, PrimitiveLiteral::Long(val)) => Ok(JsonValue::String(
677                    timestamptz::microseconds_to_datetimetz(val)
678                        .format("%Y-%m-%dT%H:%M:%S%.f+00:00")
679                        .to_string(),
680                )),
681                (PrimitiveType::TimestampNs, PrimitiveLiteral::Long(val)) => Ok(JsonValue::String(
682                    timestamp::nanoseconds_to_datetime(val)
683                        .format("%Y-%m-%dT%H:%M:%S%.f")
684                        .to_string(),
685                )),
686                (PrimitiveType::TimestamptzNs, PrimitiveLiteral::Long(val)) => {
687                    Ok(JsonValue::String(
688                        timestamptz::nanoseconds_to_datetimetz(val)
689                            .format("%Y-%m-%dT%H:%M:%S%.f+00:00")
690                            .to_string(),
691                    ))
692                }
693                (PrimitiveType::String, PrimitiveLiteral::String(val)) => {
694                    Ok(JsonValue::String(val.clone()))
695                }
696                (_, PrimitiveLiteral::UInt128(val)) => {
697                    Ok(JsonValue::String(Uuid::from_u128(val).to_string()))
698                }
699                (PrimitiveType::Fixed(size), PrimitiveLiteral::Binary(val)) => {
700                    validate_fixed_size(val.len(), *size)?;
701                    Ok(JsonValue::String(encode_hex_bytes(&val)))
702                }
703                (PrimitiveType::Binary, PrimitiveLiteral::Binary(val)) => {
704                    Ok(JsonValue::String(encode_hex_bytes(&val)))
705                }
706                (_, PrimitiveLiteral::Int128(val)) => match r#type {
707                    Type::Primitive(PrimitiveType::Decimal {
708                        precision: _precision,
709                        scale,
710                    }) => {
711                        let decimal = try_decimal_from_i128_with_scale(val, *scale)?;
712                        Ok(JsonValue::String(decimal.to_string()))
713                    }
714                    _ => Err(Error::new(
715                        ErrorKind::DataInvalid,
716                        "The iceberg type for decimal literal must be decimal.",
717                    ))?,
718                },
719                _ => Err(Error::new(
720                    ErrorKind::DataInvalid,
721                    "The iceberg value doesn't fit to the iceberg type.",
722                )),
723            },
724            (Literal::Struct(s), Type::Struct(struct_type)) => {
725                let mut id_and_value = Vec::with_capacity(struct_type.fields().len());
726                for (value, field) in s.into_iter().zip(struct_type.fields()) {
727                    let json = match value {
728                        Some(val) => val.try_into_json(&field.field_type)?,
729                        None => JsonValue::Null,
730                    };
731                    id_and_value.push((field.id.to_string(), json));
732                }
733                Ok(JsonValue::Object(JsonMap::from_iter(id_and_value)))
734            }
735            (Literal::List(list), Type::List(list_type)) => Ok(JsonValue::Array(
736                list.into_iter()
737                    .map(|opt| match opt {
738                        Some(literal) => literal.try_into_json(&list_type.element_field.field_type),
739                        None => Ok(JsonValue::Null),
740                    })
741                    .collect::<Result<Vec<JsonValue>>>()?,
742            )),
743            (Literal::Map(map), Type::Map(map_type)) => {
744                let mut object = JsonMap::with_capacity(2);
745                let mut json_keys = Vec::with_capacity(map.len());
746                let mut json_values = Vec::with_capacity(map.len());
747                for (key, value) in map.into_iter() {
748                    json_keys.push(key.try_into_json(&map_type.key_field.field_type)?);
749                    json_values.push(match value {
750                        Some(literal) => literal.try_into_json(&map_type.value_field.field_type)?,
751                        None => JsonValue::Null,
752                    });
753                }
754                object.insert("keys".to_string(), JsonValue::Array(json_keys));
755                object.insert("values".to_string(), JsonValue::Array(json_values));
756                Ok(JsonValue::Object(object))
757            }
758            (value, r#type) => Err(Error::new(
759                ErrorKind::DataInvalid,
760                format!("The iceberg value {value:?} doesn't fit to the iceberg type {type}."),
761            )),
762        }
763    }
764
765    /// Convert Value to the any type
766    pub fn into_any(self) -> Box<dyn Any> {
767        match self {
768            Literal::Primitive(prim) => match prim {
769                PrimitiveLiteral::Boolean(any) => Box::new(any),
770                PrimitiveLiteral::Int(any) => Box::new(any),
771                PrimitiveLiteral::Long(any) => Box::new(any),
772                PrimitiveLiteral::Float(any) => Box::new(any),
773                PrimitiveLiteral::Double(any) => Box::new(any),
774                PrimitiveLiteral::Binary(any) => Box::new(any),
775                PrimitiveLiteral::String(any) => Box::new(any),
776                PrimitiveLiteral::UInt128(any) => Box::new(any),
777                PrimitiveLiteral::Int128(any) => Box::new(any),
778                PrimitiveLiteral::AboveMax | PrimitiveLiteral::BelowMin => unimplemented!(),
779            },
780            _ => unimplemented!(),
781        }
782    }
783}
784
785fn decode_hex_bytes(value: &str) -> Result<Vec<u8>> {
786    if !value.len().is_multiple_of(2) {
787        return Err(Error::new(
788            ErrorKind::DataInvalid,
789            format!("Hex string must have an even number of characters: {value:?}"),
790        ));
791    }
792
793    value
794        .as_bytes()
795        .chunks_exact(2)
796        .map(|chunk| {
797            let high = decode_hex_digit(chunk[0], value)?;
798            let low = decode_hex_digit(chunk[1], value)?;
799            Ok((high << 4) | low)
800        })
801        .collect()
802}
803
804fn decode_hex_digit(digit: u8, value: &str) -> Result<u8> {
805    match digit {
806        b'0'..=b'9' => Ok(digit - b'0'),
807        b'a'..=b'f' => Ok(digit - b'a' + 10),
808        b'A'..=b'F' => Ok(digit - b'A' + 10),
809        _ => Err(Error::new(
810            ErrorKind::DataInvalid,
811            format!("Hex string contains invalid character: {value:?}"),
812        )),
813    }
814}
815
816fn encode_hex_bytes(bytes: &[u8]) -> String {
817    const HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
818
819    let mut output = String::with_capacity(bytes.len() * 2);
820    for byte in bytes {
821        output.push(HEX_DIGITS[(byte >> 4) as usize] as char);
822        output.push(HEX_DIGITS[(byte & 0x0f) as usize] as char);
823    }
824    output
825}
826
827fn validate_fixed_size(actual: usize, expected: u64) -> Result<()> {
828    if actual as u64 == expected {
829        Ok(())
830    } else {
831        Err(Error::new(
832            ErrorKind::DataInvalid,
833            format!("Fixed type must be exactly {expected} bytes, got {actual}"),
834        ))
835    }
836}