Skip to main content

linkrs_core/value/
value_convert.rs

1use crate::{
2    error::StorageError,
3    error::StorageResult,
4    types::DataType,
5    value::date_time::{DateTimeValue, DateValue, TimeValue},
6    value::interval::IntervalValue,
7    value::list::List,
8    value::null::NullType,
9    value::uuid::UuidValue,
10    value::value_def::Value,
11};
12use chrono::{Datelike, Timelike};
13
14impl Value {
15    /// Convert to a boolean value
16    pub fn to_bool(&self) -> Value {
17        match self {
18            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
19            Value::Bool(b) => Value::Bool(*b),
20            Value::SmallInt(i) => Value::Bool(*i != 0),
21            Value::Int(i) => Value::Bool(*i != 0),
22            Value::BigInt(i) => Value::Bool(*i != 0),
23            Value::Float(f) => Value::Bool(*f != 0.0),
24            Value::Double(f) => Value::Bool(*f != 0.0),
25            Value::String(s) => {
26                let lower = s.to_lowercase();
27                if lower == "true" {
28                    Value::Bool(true)
29                } else if lower == "false" {
30                    Value::Bool(false)
31                } else {
32                    Value::Null(NullType::Null)
33                }
34            }
35            Value::FixedString(data) => {
36                let lower = data.to_lowercase();
37                if lower == "true" {
38                    Value::Bool(true)
39                } else if lower == "false" {
40                    Value::Bool(false)
41                } else {
42                    Value::Null(NullType::Null)
43                }
44            }
45            _ => Value::Null(NullType::BadData),
46        }
47    }
48
49    /// Convert to BigInt (i64)
50    pub fn to_int(&self) -> Value {
51        match self {
52            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
53            Value::SmallInt(i) => Value::BigInt(*i as i64),
54            Value::Int(i) => Value::BigInt(*i as i64),
55            Value::BigInt(i) => Value::BigInt(*i),
56            Value::Float(f) => {
57                if f.is_nan() || f.is_infinite() {
58                    Value::Null(NullType::Null)
59                } else {
60                    Value::BigInt(*f as i64)
61                }
62            }
63            Value::Double(f) => {
64                if f.is_nan() || f.is_infinite() {
65                    Value::Null(NullType::Null)
66                } else {
67                    Value::BigInt(*f as i64)
68                }
69            }
70            Value::String(s) => match s.parse::<i64>() {
71                Ok(i) => Value::BigInt(i),
72                Err(_) => Value::Null(NullType::Null),
73            },
74            Value::FixedString(data) => match data.parse::<i64>() {
75                Ok(i) => Value::BigInt(i),
76                Err(_) => Value::Null(NullType::Null),
77            },
78            Value::Bool(b) => Value::BigInt(if *b { 1 } else { 0 }),
79            _ => Value::Null(NullType::BadData),
80        }
81    }
82
83    /// Convert to Double (f64)
84    pub fn to_float(&self) -> Value {
85        match self {
86            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
87            Value::Float(f) => Value::Double(*f as f64),
88            Value::Double(f) => Value::Double(*f),
89            Value::SmallInt(i) => Value::Double(*i as f64),
90            Value::Int(i) => Value::Double(*i as f64),
91            Value::BigInt(i) => Value::Double(*i as f64),
92            Value::String(s) => match s.parse::<f64>() {
93                Ok(f) => Value::Double(f),
94                Err(_) => Value::Null(NullType::Null),
95            },
96            Value::FixedString(data) => match data.parse::<f64>() {
97                Ok(f) => Value::Double(f),
98                Err(_) => Value::Null(NullType::Null),
99            },
100            Value::Bool(b) => Value::Double(if *b { 1.0 } else { 0.0 }),
101            _ => Value::Null(NullType::BadData),
102        }
103    }
104
105    /// Convert to string
106    pub fn to_string(&self) -> Result<String, String> {
107        match self {
108            Value::String(s) => Ok(s.to_string()),
109            Value::FixedString(data) => Ok(data.clone()),
110            Value::SmallInt(i) => Ok(i.to_string()),
111            Value::Int(i) => Ok(i.to_string()),
112            Value::BigInt(i) => Ok(i.to_string()),
113            Value::Float(f) => {
114                if f.is_nan() {
115                    Ok("NaN".to_string())
116                } else if f.is_infinite() {
117                    if f.is_sign_positive() {
118                        Ok("Infinity".to_string())
119                    } else {
120                        Ok("-Infinity".to_string())
121                    }
122                } else {
123                    Ok(f.to_string())
124                }
125            }
126            Value::Double(f) => {
127                if f.is_nan() {
128                    Ok("NaN".to_string())
129                } else if f.is_infinite() {
130                    if f.is_sign_positive() {
131                        Ok("Infinity".to_string())
132                    } else {
133                        Ok("-Infinity".to_string())
134                    }
135                } else {
136                    Ok(f.to_string())
137                }
138            }
139            Value::Bool(b) => Ok(b.to_string()),
140            Value::Null(n) => Ok(format!("{:?}", n)),
141            Value::Empty => Ok("EMPTY".to_string()),
142            Value::Date(d) => Ok(format!("{}-{:02}-{:02}", d.year, d.month, d.day)),
143            Value::Time(t) => Ok(format!(
144                "{:02}:{:02}:{:02}.{:06}",
145                t.hour, t.minute, t.sec, t.microsec
146            )),
147            Value::DateTime(dt) => Ok(format!(
148                "{}-{:02}-{:02} {:02}:{:02}:{:02}.{:06}",
149                dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.sec, dt.microsec
150            )),
151            Value::Uuid(u) => Ok(u.to_hyphenated_string()),
152            Value::Interval(i) => Ok(i.to_postgresql()),
153            Value::List(list) => {
154                let items: Result<Vec<String>, _> = list
155                    .iter()
156                    .map(|v| v.to_string().map_err(|e| e.to_string()))
157                    .collect();
158                items.map(|items_str| format!("[{}]", items_str.join(", ")))
159            }
160            Value::Map(map) => {
161                let items: Result<Vec<String>, _> = map
162                    .iter()
163                    .map(|(k, v)| v.to_string().map(|v_str| format!("{}: {}", k, v_str)))
164                    .collect();
165                items.map(|items_str| format!("{{{}}}", items_str.join(", ")))
166            }
167            Value::Struct(s) => {
168                let items: Result<Vec<String>, _> = s
169                    .fields
170                    .iter()
171                    .map(|(k, v)| v.to_string().map(|v_str| format!("{}: {}", k, v_str)))
172                    .collect();
173                items.map(|items_str| format!("{{{}}}", items_str.join(", ")))
174            }
175            Value::Array(a) => {
176                let items: Result<Vec<String>, _> =
177                    a.values.iter().map(|v| v.to_string()).collect();
178                items.map(|items_str| format!("[{}]", items_str.join(", ")))
179            }
180            _ => Err(format!("Cannot convert {:?} to string", self)),
181        }
182    }
183
184    /// Convert to a list
185    pub fn to_list(&self) -> Value {
186        match self {
187            Value::List(list) => Value::List(list.clone()),
188            Value::Set(set) => Value::List(Box::new(List::from(
189                set.iter().cloned().collect::<Vec<_>>(),
190            ))),
191            // Array -> List: element-wise conversion (elements are copied
192            // unchanged; element casts are applied at the type level).
193            Value::Array(array) => Value::List(Box::new(List::from(array.values.clone()))),
194            _ => Value::Null(NullType::BadData),
195        }
196    }
197
198    /// Convert to a map:
199    pub fn to_map(&self) -> Value {
200        match self {
201            Value::Map(map) => Value::Map(map.clone()),
202            // Struct -> Map: field order is preserved via the ordered map
203            // building below; HashMap loses order, matching Map semantics.
204            // Field names become string keys.
205            Value::Struct(s) => {
206                let mut map = std::collections::HashMap::new();
207                for (name, value) in &s.fields {
208                    map.insert(Value::string(name.clone()), value.clone());
209                }
210                Value::Map(Box::new(map))
211            }
212            _ => Value::Null(NullType::BadData),
213        }
214    }
215
216    /// Convert to a set
217    pub fn to_set(&self) -> Value {
218        match self {
219            Value::Set(set) => Value::Set(set.clone()),
220            Value::List(list) => Value::Set(Box::new(list.iter().cloned().collect())),
221            _ => Value::Null(NullType::BadData),
222        }
223    }
224
225    /// Convert to a date
226    pub fn to_date(&self) -> Value {
227        match self {
228            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
229            Value::Date(d) => Value::Date(d.clone()),
230            Value::DateTime(dt) => Value::Date(DateValue {
231                year: dt.year,
232                month: dt.month,
233                day: dt.day,
234            }),
235            Value::String(s) => Self::parse_date_string(s),
236            Value::FixedString(data) => Self::parse_date_string(data),
237            Value::SmallInt(i) => Value::Date(Self::days_to_date(*i as i64)),
238            Value::Int(i) => Value::Date(Self::days_to_date(*i as i64)),
239            Value::BigInt(i) => Value::Date(Self::days_to_date(*i)),
240            _ => Value::Null(NullType::BadData),
241        }
242    }
243
244    /// Convert to time
245    pub fn to_time(&self) -> Value {
246        match self {
247            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
248            Value::Time(t) => Value::Time(t.clone()),
249            Value::DateTime(dt) => Value::Time(TimeValue {
250                hour: dt.hour,
251                minute: dt.minute,
252                sec: dt.sec,
253                microsec: dt.microsec,
254            }),
255            Value::String(s) => Self::parse_time_string(s),
256            Value::FixedString(data) => Self::parse_time_string(data),
257            _ => Value::Null(NullType::BadData),
258        }
259    }
260
261    /// Convert to date and time
262    pub fn to_datetime(&self) -> Value {
263        match self {
264            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
265            Value::DateTime(dt) => Value::DateTime(dt.clone()),
266            Value::Date(d) => Value::DateTime(DateTimeValue {
267                year: d.year,
268                month: d.month,
269                day: d.day,
270                hour: 0,
271                minute: 0,
272                sec: 0,
273                microsec: 0,
274            }),
275            Value::Time(t) => Value::DateTime(DateTimeValue {
276                year: 1970,
277                month: 1,
278                day: 1,
279                hour: t.hour,
280                minute: t.minute,
281                sec: t.sec,
282                microsec: t.microsec,
283            }),
284            Value::String(s) => Self::parse_datetime_string(s),
285            Value::FixedString(data) => Self::parse_datetime_string(data),
286            Value::SmallInt(i) => {
287                let date = Self::days_to_date(*i as i64);
288                Value::DateTime(DateTimeValue {
289                    year: date.year,
290                    month: date.month,
291                    day: date.day,
292                    hour: 0,
293                    minute: 0,
294                    sec: 0,
295                    microsec: 0,
296                })
297            }
298            Value::Int(i) => {
299                let date = Self::days_to_date(*i as i64);
300                Value::DateTime(DateTimeValue {
301                    year: date.year,
302                    month: date.month,
303                    day: date.day,
304                    hour: 0,
305                    minute: 0,
306                    sec: 0,
307                    microsec: 0,
308                })
309            }
310            Value::BigInt(i) => {
311                let date = Self::days_to_date(*i);
312                Value::DateTime(DateTimeValue {
313                    year: date.year,
314                    month: date.month,
315                    day: date.day,
316                    hour: 0,
317                    minute: 0,
318                    sec: 0,
319                    microsec: 0,
320                })
321            }
322            _ => Value::Null(NullType::BadData),
323        }
324    }
325
326    /// Convert to interval
327    pub fn to_interval(&self) -> Value {
328        match self {
329            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
330            Value::Interval(i) => Value::Interval(*i),
331            Value::String(s) => match IntervalValue::parse(s) {
332                Ok(i) => Value::Interval(i),
333                Err(_) => Value::Null(NullType::BadData),
334            },
335            Value::FixedString(data) => match IntervalValue::parse(data) {
336                Ok(i) => Value::Interval(i),
337                Err(_) => Value::Null(NullType::BadData),
338            },
339            _ => Value::Null(NullType::BadData),
340        }
341    }
342
343    fn parse_date_string(s: &str) -> Value {
344        let formats = vec!["%Y-%m-%d", "%Y/%m/%d", "%Y%m%d"];
345
346        for format in &formats {
347            if let Ok(dt) = chrono::NaiveDate::parse_from_str(s, format) {
348                return Value::Date(DateValue {
349                    year: dt.year(),
350                    month: dt.month(),
351                    day: dt.day(),
352                });
353            }
354        }
355
356        Value::Null(NullType::BadData)
357    }
358
359    fn parse_time_string(s: &str) -> Value {
360        let formats = vec!["%H:%M:%S", "%H:%M:%S%.f", "%H:%M"];
361
362        for format in &formats {
363            if let Ok(time) = chrono::NaiveTime::parse_from_str(s, format) {
364                return Value::Time(TimeValue {
365                    hour: time.hour(),
366                    minute: time.minute(),
367                    sec: time.second(),
368                    microsec: time.nanosecond() / 1000,
369                });
370            }
371        }
372
373        Value::Null(NullType::BadData)
374    }
375
376    fn parse_datetime_string(s: &str) -> Value {
377        let formats = vec![
378            "%Y-%m-%d %H:%M:%S",
379            "%Y-%m-%d %H:%M:%S%.f",
380            "%Y-%m-%dT%H:%M:%S",
381            "%Y-%m-%dT%H:%M:%S%.f",
382            "%Y/%m/%d %H:%M:%S",
383        ];
384
385        for format in &formats {
386            if let Ok(dt) = chrono::NaiveDateTime::parse_from_str(s, format) {
387                return Value::DateTime(DateTimeValue {
388                    year: dt.year(),
389                    month: dt.month(),
390                    day: dt.day(),
391                    hour: dt.hour(),
392                    minute: dt.minute(),
393                    sec: dt.second(),
394                    microsec: dt.nanosecond() / 1000,
395                });
396            }
397        }
398
399        Value::Null(NullType::BadData)
400    }
401
402    fn days_to_date(days: i64) -> DateValue {
403        let epoch = match chrono::NaiveDate::from_ymd_opt(1970, 1, 1) {
404            Some(date) => date,
405            None => {
406                return DateValue {
407                    year: 1970,
408                    month: 1,
409                    day: 1,
410                }
411            }
412        };
413        let date = epoch + chrono::Duration::days(days);
414        DateValue {
415            year: date.year(),
416            month: date.month(),
417            day: date.day(),
418        }
419    }
420
421    /// Try to implicitly convert to the specified type.
422    pub fn try_implicit_cast(&self, target_type: &DataType) -> Result<Value, String> {
423        match target_type {
424            DataType::Bool => Ok(self.to_bool()),
425            DataType::SmallInt => Ok(self.to_smallint()),
426            DataType::Int => Ok(self.to_int32()),
427            DataType::BigInt => Ok(self.to_int()),
428            DataType::Float => Ok(self.to_float32()),
429            DataType::Double => Ok(self.to_float()),
430            DataType::String => self.to_string().map(Value::string),
431            DataType::FixedString(len) => match self {
432                Value::String(s) => Ok(Value::fixed_string(*len, s.to_string())),
433                Value::FixedString(s) => Ok(Value::fixed_string(*len, s.clone())),
434                _ => self.to_string().map(|s| Value::fixed_string(*len, s)),
435            },
436            DataType::Date => Ok(self.to_date()),
437            DataType::Time => Ok(self.to_time()),
438            DataType::DateTime => Ok(self.to_datetime()),
439            DataType::Uuid => Ok(self.to_uuid()),
440            DataType::Interval => Ok(self.to_interval()),
441            _ => Err(format!("Cannot implicitly cast to {:?}", target_type)),
442        }
443    }
444
445    /// Convert to SmallInt (i16)
446    pub fn to_smallint(&self) -> Value {
447        match self {
448            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
449            Value::SmallInt(i) => Value::SmallInt(*i),
450            Value::Int(i) => Value::SmallInt(*i as i16),
451            Value::BigInt(i) => Value::SmallInt(*i as i16),
452            Value::Float(f) => Value::SmallInt(*f as i16),
453            Value::Double(f) => Value::SmallInt(*f as i16),
454            Value::String(s) => match s.parse::<i16>() {
455                Ok(i) => Value::SmallInt(i),
456                Err(_) => Value::Null(NullType::Null),
457            },
458            Value::FixedString(data) => match data.parse::<i16>() {
459                Ok(i) => Value::SmallInt(i),
460                Err(_) => Value::Null(NullType::Null),
461            },
462            Value::Bool(b) => Value::SmallInt(if *b { 1 } else { 0 }),
463            _ => Value::Null(NullType::BadData),
464        }
465    }
466
467    /// Convert to Int (i32)
468    pub fn to_int32(&self) -> Value {
469        match self {
470            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
471            Value::SmallInt(i) => Value::Int(*i as i32),
472            Value::Int(i) => Value::Int(*i),
473            Value::BigInt(i) => Value::Int(*i as i32),
474            Value::Float(f) => Value::Int(*f as i32),
475            Value::Double(f) => Value::Int(*f as i32),
476            Value::String(s) => match s.parse::<i32>() {
477                Ok(i) => Value::Int(i),
478                Err(_) => Value::Null(NullType::Null),
479            },
480            Value::FixedString(data) => match data.parse::<i32>() {
481                Ok(i) => Value::Int(i),
482                Err(_) => Value::Null(NullType::Null),
483            },
484            Value::Bool(b) => Value::Int(if *b { 1 } else { 0 }),
485            _ => Value::Null(NullType::BadData),
486        }
487    }
488
489    /// Convert to Float (f32)
490    pub fn to_float32(&self) -> Value {
491        match self {
492            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
493            Value::Float(f) => Value::Float(*f),
494            Value::Double(f) => Value::Float(*f as f32),
495            Value::SmallInt(i) => Value::Float(*i as f32),
496            Value::Int(i) => Value::Float(*i as f32),
497            Value::BigInt(i) => Value::Float(*i as f32),
498            Value::String(s) => match s.parse::<f32>() {
499                Ok(f) => Value::Float(f),
500                Err(_) => Value::Null(NullType::Null),
501            },
502            Value::FixedString(data) => match data.parse::<f32>() {
503                Ok(f) => Value::Float(f),
504                Err(_) => Value::Null(NullType::Null),
505            },
506            Value::Bool(b) => Value::Float(if *b { 1.0 } else { 0.0 }),
507            _ => Value::Null(NullType::BadData),
508        }
509    }
510
511    /// Check whether an implicit conversion is possible.
512    pub fn can_implicitly_cast_to(&self, target_type: &DataType) -> bool {
513        self.try_implicit_cast(target_type).is_ok()
514    }
515
516    /// Check whether the value is a valid number.
517    pub fn is_valid_number(&self) -> bool {
518        match self {
519            Value::SmallInt(_) | Value::Int(_) | Value::BigInt(_) => true,
520            Value::Float(f) => !f.is_nan() && !f.is_infinite(),
521            Value::Double(f) => !f.is_nan() && !f.is_infinite(),
522            _ => false,
523        }
524    }
525
526    /// Check whether the value is a valid date.
527    pub fn is_valid_date(&self) -> bool {
528        match self {
529            Value::Date(d) => {
530                d.year >= 0
531                    && d.year <= 9999
532                    && d.month >= 1
533                    && d.month <= 12
534                    && d.day >= 1
535                    && d.day <= 31
536            }
537            _ => false,
538        }
539    }
540
541    /// Check whether the value represents a valid time.
542    pub fn is_valid_time(&self) -> bool {
543        match self {
544            Value::Time(t) => t.hour <= 23 && t.minute <= 59 && t.sec <= 59 && t.microsec <= 999999,
545            _ => false,
546        }
547    }
548
549    /// Check whether the value is a valid date and time.
550    pub fn is_valid_datetime(&self) -> bool {
551        match self {
552            Value::DateTime(dt) => {
553                dt.year >= 0
554                    && dt.year <= 9999
555                    && dt.month >= 1
556                    && dt.month <= 12
557                    && dt.day >= 1
558                    && dt.day <= 31
559                    && dt.hour <= 23
560                    && dt.minute <= 59
561                    && dt.sec <= 59
562                    && dt.microsec <= 999999
563            }
564            _ => false,
565        }
566    }
567}
568
569impl From<bool> for Value {
570    fn from(value: bool) -> Self {
571        Value::Bool(value)
572    }
573}
574
575impl From<i16> for Value {
576    fn from(value: i16) -> Self {
577        Value::SmallInt(value)
578    }
579}
580
581impl From<i32> for Value {
582    fn from(value: i32) -> Self {
583        Value::Int(value)
584    }
585}
586
587impl From<i64> for Value {
588    fn from(value: i64) -> Self {
589        Value::BigInt(value)
590    }
591}
592
593impl From<f32> for Value {
594    fn from(value: f32) -> Self {
595        Value::Float(value)
596    }
597}
598
599impl From<f64> for Value {
600    fn from(value: f64) -> Self {
601        Value::Double(value)
602    }
603}
604
605impl From<String> for Value {
606    fn from(value: String) -> Self {
607        Value::string(value)
608    }
609}
610
611impl From<UuidValue> for Value {
612    fn from(value: UuidValue) -> Self {
613        Value::Uuid(value)
614    }
615}
616
617impl From<IntervalValue> for Value {
618    fn from(value: IntervalValue) -> Self {
619        Value::Interval(value)
620    }
621}
622
623impl Value {
624    /// Convert to UUID
625    pub fn to_uuid(&self) -> Value {
626        match self {
627            Value::Empty | Value::Null(_) => Value::Null(NullType::Null),
628            Value::Uuid(u) => Value::Uuid(*u),
629            Value::String(s) => match UuidValue::parse_str(s) {
630                Ok(u) => Value::Uuid(u),
631                Err(_) => Value::Null(NullType::BadData),
632            },
633            Value::FixedString(data) => match UuidValue::parse_str(data) {
634                Ok(u) => Value::Uuid(u),
635                Err(_) => Value::Null(NullType::BadData),
636            },
637            Value::Blob(b) => match UuidValue::from_slice(b) {
638                Ok(u) => Value::Uuid(u),
639                Err(_) => Value::Null(NullType::BadData),
640            },
641            _ => Value::Null(NullType::BadData),
642        }
643    }
644
645    /// Try to cast this value to the target data type.
646    /// Returns the converted value on success, or a type_mismatch error.
647    /// Supports implicit type conversions that are allowed by TypeUtils::can_cast.
648    pub fn try_cast_to(&self, target: &DataType) -> StorageResult<Value> {
649        if self.data_type() == *target {
650            return Ok(self.clone());
651        }
652
653        // Boolean values cannot be coerced into numeric types.
654        if matches!(self, Value::Bool(_))
655            && matches!(
656                target,
657                DataType::SmallInt
658                    | DataType::Int
659                    | DataType::BigInt
660                    | DataType::Float
661                    | DataType::Double
662            )
663        {
664            return Err(StorageError::type_mismatch(
665                target.clone(),
666                self.data_type(),
667            ));
668        }
669
670        let result = match target {
671            DataType::Null | DataType::Empty => Value::Null(NullType::Null),
672            DataType::Bool => self.to_bool(),
673            DataType::SmallInt => match self.to_int() {
674                Value::BigInt(i) if i >= i16::MIN as i64 && i <= i16::MAX as i64 => {
675                    Value::SmallInt(i as i16)
676                }
677                Value::BigInt(_) => {
678                    return Err(StorageError::type_mismatch(
679                        DataType::SmallInt,
680                        self.data_type(),
681                    ));
682                }
683                Value::Null(_) if self.is_null() => Value::Null(NullType::Null),
684                _ => {
685                    return Err(StorageError::type_mismatch(
686                        DataType::SmallInt,
687                        self.data_type(),
688                    ));
689                }
690            },
691            DataType::Int => match self.to_int() {
692                Value::BigInt(i) if i >= i32::MIN as i64 && i <= i32::MAX as i64 => {
693                    Value::Int(i as i32)
694                }
695                Value::BigInt(_) => {
696                    return Err(StorageError::type_mismatch(DataType::Int, self.data_type()));
697                }
698                Value::Null(_) if self.is_null() => Value::Null(NullType::Null),
699                _ => {
700                    return Err(StorageError::type_mismatch(DataType::Int, self.data_type()));
701                }
702            },
703            DataType::BigInt => match self.to_int() {
704                Value::Null(_) if self.is_null() => Value::Null(NullType::Null),
705                Value::Null(_) => {
706                    return Err(StorageError::type_mismatch(
707                        DataType::BigInt,
708                        self.data_type(),
709                    ));
710                }
711                other => other,
712            },
713            DataType::Float => match self.to_float() {
714                Value::Double(f) => Value::Float(f as f32),
715                Value::Null(_) if self.is_null() => Value::Null(NullType::Null),
716                _ => {
717                    return Err(StorageError::type_mismatch(
718                        DataType::Float,
719                        self.data_type(),
720                    ));
721                }
722            },
723            DataType::Double => match self.to_float() {
724                Value::Null(_) if self.is_null() => Value::Null(NullType::Null),
725                Value::Null(_) => {
726                    return Err(StorageError::type_mismatch(
727                        DataType::Double,
728                        self.data_type(),
729                    ));
730                }
731                other => other,
732            },
733            DataType::String => match self.to_string() {
734                Ok(s) => Value::string(s),
735                Err(_) => Value::Null(NullType::BadData),
736            },
737            DataType::Date => self.to_date(),
738            DataType::Time => self.to_time(),
739            DataType::DateTime => self.to_datetime(),
740            DataType::List(_) => self.to_list(),
741            DataType::Map(_) => self.to_map(),
742            DataType::Struct(target_info) => match self {
743                Value::Null(_) | Value::Empty => Value::Null(NullType::Null),
744                Value::Struct(_) => self.clone(),
745                // Map -> Struct: field-name isomorphism; the Map value type
746                // must be castable to the target field types (enforced at
747                // value level by direct copy when types already match).
748                Value::Map(map) => {
749                    let fields = target_info
750                        .fields
751                        .iter()
752                        .map(|(name, _)| {
753                            let key = Value::string(name.clone());
754                            (
755                                name.clone(),
756                                map.get(&key)
757                                    .cloned()
758                                    .unwrap_or(Value::Null(NullType::Null)),
759                            )
760                        })
761                        .collect();
762                    Value::Struct(Box::new(crate::StructValue::new(fields)))
763                }
764                _ => {
765                    return Err(StorageError::type_mismatch(
766                        target.clone(),
767                        self.data_type(),
768                    ))
769                }
770            },
771            DataType::Array(_) => match self {
772                Value::Null(_) | Value::Empty => Value::Null(NullType::Null),
773                Value::Array(_) => self.clone(),
774                // List -> Array: element copy; element type compatibility is
775                // validated by `TypeUtils::can_cast` before this path runs.
776                Value::List(list) => Value::Array(Box::new(crate::ArrayValue::new(
777                    list.iter().cloned().collect(),
778                ))),
779                _ => {
780                    return Err(StorageError::type_mismatch(
781                        target.clone(),
782                        self.data_type(),
783                    ))
784                }
785            },
786            DataType::Geography => match self {
787                Value::Null(_) | Value::Empty => Value::Null(NullType::Null),
788                Value::Geography(g) => Value::Geography(g.clone()),
789                _ => {
790                    return Err(StorageError::type_mismatch(
791                        target.clone(),
792                        self.data_type(),
793                    ))
794                }
795            },
796            DataType::VectorDense(dim) => match self {
797                Value::Null(_) | Value::Empty => Value::Null(NullType::Null),
798                Value::Vector(v) => {
799                    let actual_dim = v.dimension();
800                    if actual_dim == *dim {
801                        Value::Vector(v.clone())
802                    } else {
803                        return Err(StorageError::type_mismatch(
804                            DataType::VectorDense(*dim),
805                            DataType::VectorDense(actual_dim),
806                        ));
807                    }
808                }
809                Value::List(list) => {
810                    if list.len() != *dim {
811                        return Err(StorageError::type_mismatch(
812                            DataType::VectorDense(*dim),
813                            self.data_type(),
814                        ));
815                    }
816                    let vec_data: Option<Vec<f32>> = list
817                        .iter()
818                        .map(|v| match v {
819                            Value::Float(f) => Some(*f),
820                            Value::Double(d) => Some(*d as f32),
821                            Value::Int(i) => Some(*i as f32),
822                            Value::SmallInt(i) => Some(*i as f32),
823                            Value::BigInt(i) => Some(*i as f32),
824                            _ => None,
825                        })
826                        .collect();
827                    match vec_data {
828                        Some(data) => Value::vector(data),
829                        None => {
830                            return Err(StorageError::type_mismatch(
831                                target.clone(),
832                                self.data_type(),
833                            ))
834                        }
835                    }
836                }
837                _ => {
838                    return Err(StorageError::type_mismatch(
839                        target.clone(),
840                        self.data_type(),
841                    ))
842                }
843            },
844            _ => Value::Null(NullType::BadData),
845        };
846
847        if matches!(result, Value::Null(NullType::BadData)) {
848            Err(StorageError::type_mismatch(
849                target.clone(),
850                self.data_type(),
851            ))
852        } else {
853            Ok(result)
854        }
855    }
856}
857
858impl From<&str> for Value {
859    fn from(value: &str) -> Self {
860        Value::string(value)
861    }
862}
863
864impl From<NullType> for Value {
865    fn from(value: NullType) -> Self {
866        Value::Null(value)
867    }
868}
869
870impl From<Vec<Value>> for Value {
871    fn from(value: Vec<Value>) -> Self {
872        Value::list(List::from(value))
873    }
874}
875
876impl From<std::collections::HashMap<String, Value>> for Value {
877    fn from(value: std::collections::HashMap<String, Value>) -> Self {
878        Value::string_map(value)
879    }
880}
881
882impl From<std::collections::HashMap<Value, Value>> for Value {
883    fn from(value: std::collections::HashMap<Value, Value>) -> Self {
884        Value::map(value)
885    }
886}
887
888impl From<std::collections::HashSet<Value>> for Value {
889    fn from(value: std::collections::HashSet<Value>) -> Self {
890        Value::set(value)
891    }
892}
893
894impl From<(i64, &str)> for Value {
895    fn from(value: (i64, &str)) -> Self {
896        Value::list(List::from(vec![
897            Value::BigInt(value.0),
898            Value::string(value.1),
899        ]))
900    }
901}
902
903impl From<(i64, String)> for Value {
904    fn from(value: (i64, String)) -> Self {
905        Value::list(List::from(vec![
906            Value::BigInt(value.0),
907            Value::string(value.1),
908        ]))
909    }
910}