Skip to main content

google_cloud_spanner/
from_value.rs

1// Copyright 2026 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15pub use crate::types::{Type, TypeCode};
16use crate::value::Kind;
17use crate::value::Value;
18use base64::Engine;
19use base64::prelude::BASE64_STANDARD;
20use rust_decimal::Decimal;
21use serde_json::Value as JsonValue;
22use std::time::SystemTime;
23use time::{Date, OffsetDateTime};
24
25/// Represent failures in converting a Spanner Value to a Rust type.
26#[derive(thiserror::Error, Debug)]
27#[non_exhaustive]
28pub enum ConvertError {
29    /// The value kind is not as expected.
30    #[error("expected {want:?}, got {got:?}")]
31    KindMismatch {
32        /// The expected Spanner value kind.
33        want: Kind,
34        /// The actual Spanner value kind.
35        got: Kind,
36    },
37
38    /// The value is null, but the target type does not support nulls.
39    #[error("expected non-null value, got null")]
40    NotNull,
41
42    /// There was a problem during conversion.
43    #[error("cannot convert value, source={0}")]
44    Convert(#[source] BoxedError),
45}
46
47type BoxedError = Box<dyn std::error::Error + Send + Sync>;
48
49/// Converts a Spanner [Value] into a Rust type.
50///
51/// Implementations are provided for all standard types like `String`, primitive integer
52/// and float types, decimals, timestamps, dates, vectors, and options for nullable fields.
53pub trait FromValue: Sized {
54    /// Converts a Spanner value into the target Rust type, using the provided
55    /// Spanner `Type` metadata for compatibility checks.
56    ///
57    /// # Errors
58    ///
59    /// Returns a [`ConvertError`] if the kind of the value does not match the expected kind,
60    /// if the value is null but the target type is not optional (e.g., `Option<T>`), or if
61    /// parsing or decoding the inner value format fails.
62    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError>;
63}
64
65impl<T> FromValue for Option<T>
66where
67    T: FromValue,
68{
69    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
70        match &value.0.kind {
71            Some(prost_types::value::Kind::NullValue(_)) => Ok(None),
72            _ => T::from_value(value, type_).map(Some),
73        }
74    }
75}
76
77impl FromValue for Value {
78    fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
79        Ok(value.clone())
80    }
81}
82
83/// Converts any Spanner [`Value`] into a [`serde_json::Value`] using runtime [`Type`] metadata.
84///
85/// This enables dynamic deserialization of STRUCT, ARRAY, and nested
86/// `ARRAY<STRUCT<ARRAY<...>>>` columns without requiring predefined Rust types.
87///
88/// # Type mapping
89///
90/// | Spanner wire format | JSON output |
91/// |---------------------|-------------|
92/// | `NullValue` | `null` |
93/// | `BoolValue` | `true` / `false` |
94/// | `NumberValue` (finite) | JSON number |
95/// | `NumberValue` (NaN/±Infinity) | `null` (matches SDK's `into_serde_value`) |
96/// | `StringValue` (standard) | JSON string (includes stringified `INT64`, `NUMERIC`, Base64 `BYTES`, `TIMESTAMP`, `DATE`) |
97/// | `StringValue` (+ `TypeCode::Json`) | Parsed JSON object/array/value |
98/// | `ListValue` + `TypeCode::Struct` | JSON object (positional → named via metadata) |
99/// | `ListValue` + `TypeCode::Array` | JSON array |
100/// | `StructValue` (named wire format) | JSON object |
101///
102/// # Known limitations
103///
104/// - **Precision Safety**: Types such as `INT64`, `NUMERIC`, and temporal types (which
105///   Spanner transmits as `StringValue` on the wire) are preserved as JSON strings.
106///   This prevents precision loss (e.g. for integers exceeding $2^{53}-1$ or
107///   high-precision decimals) during deserialization.
108/// - **NaN/Infinity → null**: Non-finite floats become `null` since JSON has no
109///   representation. Callers cannot distinguish these from genuine SQL NULLs.
110/// - **Duplicate field names**: Spanner allows structs with duplicate field names
111///   (e.g., unnamed columns). Since JSON objects require unique keys, last-write-wins
112///   applies via `serde_json::Map::insert`.
113/// - **Missing struct metadata**: When `TypeCode::Struct` is indicated but no
114///   `struct_type` metadata is available, positional values are returned as a plain
115///   JSON array to avoid silent data loss.
116impl FromValue for JsonValue {
117    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
118        from_value_recursive(value, Some(type_), 0)
119    }
120}
121
122fn from_value_recursive(
123    value: &Value,
124    type_: Option<&Type>,
125    depth: usize,
126) -> Result<JsonValue, ConvertError> {
127    const MAX_RECURSION_DEPTH: usize = 64;
128    if depth > MAX_RECURSION_DEPTH {
129        return Err(ConvertError::Convert(
130            "maximum nesting depth exceeded".into(),
131        ));
132    }
133
134    match &value.0.kind {
135        Some(prost_types::value::Kind::NullValue(_)) => Ok(JsonValue::Null),
136
137        Some(prost_types::value::Kind::NumberValue(n)) => Ok(serde_json::Number::from_f64(*n)
138            .map(JsonValue::Number)
139            .unwrap_or(JsonValue::Null)),
140
141        Some(prost_types::value::Kind::StringValue(s)) => {
142            let Some(t) = type_ else {
143                return Ok(JsonValue::String(s.clone()));
144            };
145            match t.code() {
146                TypeCode::Json => {
147                    serde_json::from_str(s).map_err(|e| ConvertError::Convert(Box::new(e)))
148                }
149                TypeCode::Float64 | TypeCode::Float32 => {
150                    if s == "NaN" || s == "Infinity" || s == "-Infinity" {
151                        return Ok(JsonValue::Null);
152                    }
153                    let f = s
154                        .parse::<f64>()
155                        .map_err(|e| ConvertError::Convert(Box::new(e)))?;
156                    Ok(serde_json::Number::from_f64(f)
157                        .map(JsonValue::Number)
158                        .unwrap_or(JsonValue::Null))
159                }
160                _ => Ok(JsonValue::String(s.clone())),
161            }
162        }
163
164        Some(prost_types::value::Kind::BoolValue(b)) => Ok(JsonValue::Bool(*b)),
165
166        Some(prost_types::value::Kind::StructValue(s)) => struct_value_to_json(s, type_, depth + 1),
167
168        Some(prost_types::value::Kind::ListValue(list)) => {
169            list_value_to_json(list, type_, depth + 1)
170        }
171
172        None => Ok(JsonValue::Null),
173    }
174}
175
176fn struct_value_to_json(
177    s: &prost_types::Struct,
178    type_: Option<&Type>,
179    depth: usize,
180) -> Result<JsonValue, ConvertError> {
181    let s = crate::value::Struct::from_ref(s);
182    let mut map = serde_json::Map::new();
183
184    let Some(struct_type) = type_.and_then(|t| t.struct_type()) else {
185        for (k, v) in s.fields() {
186            map.insert(k.clone(), from_value_recursive(v, None, depth)?);
187        }
188        return Ok(JsonValue::Object(map));
189    };
190
191    for field in &struct_type.fields {
192        let field_type = field.r#type.as_deref().map(Type::from_ref);
193        let value = if let Some(v) = s.get(&field.name) {
194            from_value_recursive(v, field_type, depth)?
195        } else {
196            JsonValue::Null
197        };
198        map.insert(field.name.clone(), value);
199    }
200
201    Ok(JsonValue::Object(map))
202}
203
204fn list_value_to_json(
205    list: &prost_types::ListValue,
206    type_: Option<&Type>,
207    depth: usize,
208) -> Result<JsonValue, ConvertError> {
209    let code = type_.map_or(TypeCode::Unspecified, |t| t.code());
210    match code {
211        TypeCode::Struct => {
212            let Some(struct_type) = type_.and_then(|t| t.struct_type()) else {
213                let mut arr = Vec::with_capacity(list.values.len());
214                for v in &list.values {
215                    let val = Value::from_ref(v);
216                    arr.push(from_value_recursive(val, None, depth)?);
217                }
218                return Ok(JsonValue::Array(arr));
219            };
220
221            let mut map = serde_json::Map::new();
222            for (i, field) in struct_type.fields.iter().enumerate() {
223                let field_type = field.r#type.as_deref().map(Type::from_ref);
224                let value = if let Some(v) = list.values.get(i) {
225                    let val = Value::from_ref(v);
226                    from_value_recursive(val, field_type, depth)?
227                } else {
228                    JsonValue::Null
229                };
230                map.insert(field.name.clone(), value);
231            }
232            Ok(JsonValue::Object(map))
233        }
234
235        TypeCode::Array => {
236            let element_type = type_.and_then(|t| t.array_element_type());
237            let mut arr = Vec::with_capacity(list.values.len());
238            for v in &list.values {
239                let val = Value::from_ref(v);
240                arr.push(from_value_recursive(val, element_type.as_ref(), depth)?);
241            }
242            Ok(JsonValue::Array(arr))
243        }
244
245        _ => {
246            let mut arr = Vec::with_capacity(list.values.len());
247            for v in &list.values {
248                let val = Value::from_ref(v);
249                arr.push(from_value_recursive(val, None, depth)?);
250            }
251            Ok(JsonValue::Array(arr))
252        }
253    }
254}
255
256impl FromValue for String {
257    fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
258        match &value.0.kind {
259            Some(prost_types::value::Kind::StringValue(s)) => Ok(s.clone()),
260            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
261            _ => Err(ConvertError::KindMismatch {
262                want: crate::value::Kind::String,
263                got: value.kind(),
264            }),
265        }
266    }
267}
268
269impl FromValue for i64 {
270    fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
271        match &value.0.kind {
272            Some(prost_types::value::Kind::StringValue(s)) => {
273                s.parse().map_err(|e| ConvertError::Convert(Box::new(e)))
274            }
275            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
276            _ => Err(ConvertError::KindMismatch {
277                want: crate::value::Kind::String,
278                got: value.kind(),
279            }),
280        }
281    }
282}
283
284impl FromValue for i32 {
285    fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
286        match &value.0.kind {
287            Some(prost_types::value::Kind::StringValue(s)) => {
288                s.parse().map_err(|e| ConvertError::Convert(Box::new(e)))
289            }
290            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
291            _ => Err(ConvertError::KindMismatch {
292                want: crate::value::Kind::String,
293                got: value.kind(),
294            }),
295        }
296    }
297}
298
299impl FromValue for Decimal {
300    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
301        if type_.code() != TypeCode::Numeric {
302            return Err(ConvertError::KindMismatch {
303                want: crate::value::Kind::String,
304                got: value.kind(),
305            });
306        }
307        match &value.0.kind {
308            Some(prost_types::value::Kind::StringValue(s)) => {
309                Decimal::from_str_exact(s).map_err(|e| ConvertError::Convert(Box::new(e)))
310            }
311            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
312            _ => Err(ConvertError::KindMismatch {
313                want: crate::value::Kind::String,
314                got: value.kind(),
315            }),
316        }
317    }
318}
319
320impl FromValue for SystemTime {
321    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
322        if type_.code() != TypeCode::Timestamp {
323            return Err(ConvertError::KindMismatch {
324                want: crate::value::Kind::String,
325                got: value.kind(),
326            });
327        }
328        match &value.0.kind {
329            Some(prost_types::value::Kind::StringValue(s)) => {
330                let dt = OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339)
331                    .map_err(|e| ConvertError::Convert(Box::new(e)))?;
332                Ok(dt.into())
333            }
334            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
335            _ => Err(ConvertError::KindMismatch {
336                want: crate::value::Kind::String,
337                got: value.kind(),
338            }),
339        }
340    }
341}
342
343impl FromValue for OffsetDateTime {
344    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
345        if type_.code() != TypeCode::Timestamp {
346            return Err(ConvertError::KindMismatch {
347                want: crate::value::Kind::String,
348                got: value.kind(),
349            });
350        }
351        match &value.0.kind {
352            Some(prost_types::value::Kind::StringValue(s)) => {
353                let dt = OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339)
354                    .map_err(|e| ConvertError::Convert(Box::new(e)))?;
355                Ok(dt)
356            }
357            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
358            _ => Err(ConvertError::KindMismatch {
359                want: crate::value::Kind::String,
360                got: value.kind(),
361            }),
362        }
363    }
364}
365
366impl FromValue for wkt::Timestamp {
367    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
368        let dt = OffsetDateTime::from_value(value, type_)?;
369        wkt::Timestamp::try_from(dt).map_err(|e| ConvertError::Convert(Box::new(e)))
370    }
371}
372
373impl FromValue for Date {
374    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
375        if type_.code() != TypeCode::Date {
376            return Err(ConvertError::KindMismatch {
377                want: crate::value::Kind::String,
378                got: value.kind(),
379            });
380        }
381        match &value.0.kind {
382            Some(prost_types::value::Kind::StringValue(s)) => {
383                let date = Date::parse(s, crate::value::SPANNER_DATE_FORMAT)
384                    .map_err(|e| ConvertError::Convert(Box::new(e)))?;
385                Ok(date)
386            }
387            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
388            _ => Err(ConvertError::KindMismatch {
389                want: crate::value::Kind::String,
390                got: value.kind(),
391            }),
392        }
393    }
394}
395
396impl FromValue for bool {
397    fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
398        match &value.0.kind {
399            Some(prost_types::value::Kind::BoolValue(b)) => Ok(*b),
400            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
401            _ => Err(ConvertError::KindMismatch {
402                want: crate::value::Kind::Bool,
403                got: value.kind(),
404            }),
405        }
406    }
407}
408
409impl FromValue for f64 {
410    fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
411        match &value.0.kind {
412            Some(prost_types::value::Kind::NumberValue(n)) => Ok(*n),
413            Some(prost_types::value::Kind::StringValue(s)) => {
414                s.parse().map_err(|e| ConvertError::Convert(Box::new(e)))
415            }
416            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
417            _ => Err(ConvertError::KindMismatch {
418                want: crate::value::Kind::Number,
419                got: value.kind(),
420            }),
421        }
422    }
423}
424
425impl FromValue for f32 {
426    fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
427        match &value.0.kind {
428            Some(prost_types::value::Kind::NumberValue(n)) => Ok(*n as f32),
429            Some(prost_types::value::Kind::StringValue(s)) => {
430                s.parse().map_err(|e| ConvertError::Convert(Box::new(e)))
431            }
432            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
433            _ => Err(ConvertError::KindMismatch {
434                want: crate::value::Kind::Number,
435                got: value.kind(),
436            }),
437        }
438    }
439}
440
441impl FromValue for Vec<u8> {
442    fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
443        if type_.code() != TypeCode::Bytes && type_.code() != TypeCode::Proto {
444            return Err(ConvertError::KindMismatch {
445                want: crate::value::Kind::String,
446                got: value.kind(),
447            });
448        }
449        match &value.0.kind {
450            Some(prost_types::value::Kind::StringValue(s)) => BASE64_STANDARD
451                .decode(s)
452                .map_err(|e| ConvertError::Convert(Box::new(e))),
453            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
454            _ => Err(ConvertError::KindMismatch {
455                want: crate::value::Kind::String,
456                got: value.kind(),
457            }),
458        }
459    }
460}
461
462impl<T> FromValue for Vec<T>
463where
464    T: FromValue,
465{
466    fn from_value(value: &Value, r#type: &Type) -> Result<Self, ConvertError> {
467        if r#type.code() != TypeCode::Array {
468            return Err(ConvertError::KindMismatch {
469                want: crate::value::Kind::List,
470                got: value.kind(),
471            });
472        }
473        let element_type = r#type
474            .array_element_type()
475            .ok_or_else(|| ConvertError::Convert("Array type missing element type".into()))?;
476
477        match &value.0.kind {
478            Some(prost_types::value::Kind::ListValue(list)) => {
479                let mut vec = Vec::with_capacity(list.values.len());
480                for v in &list.values {
481                    // `Value` is a `#[repr(transparent)]` wrapper around `ProtoValue`.
482                    // We use `from_ref` to safely cast the pointer and avoid cloning elements.
483                    let val = crate::value::Value::from_ref(v);
484                    vec.push(T::from_value(val, &element_type)?);
485                }
486                Ok(vec)
487            }
488            Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
489            _ => Err(ConvertError::KindMismatch {
490                want: crate::value::Kind::List,
491                got: value.kind(),
492            }),
493        }
494    }
495}
496
497#[cfg(test)]
498mod tests {
499    use super::*;
500    use crate::generated::gapic_dataplane::model as mdl;
501    use crate::to_value::ToValue;
502    use crate::types;
503    use serde_json::Value as JsonValue;
504
505    #[test]
506    fn test_from_value_string() {
507        let v = "hello".to_value();
508        let s = String::from_value(&v, &types::string()).unwrap();
509        assert_eq!(s, "hello");
510    }
511
512    #[test]
513    fn test_from_value_int() {
514        let v = 42i64.to_value();
515        let i = i64::from_value(&v, &types::int64()).unwrap();
516        assert_eq!(i, 42);
517
518        let v = 42i32.to_value();
519        let i = i32::from_value(&v, &types::int64()).unwrap();
520        assert_eq!(i, 42);
521
522        // Negative tests
523        let v = "not an int".to_value();
524        let err = i64::from_value(&v, &types::int64()).unwrap_err();
525        assert!(format!("{}", err).contains("cannot convert value"));
526
527        let v = "not an int".to_value();
528        let err = i32::from_value(&v, &types::int64()).unwrap_err();
529        assert!(format!("{}", err).contains("cannot convert value"));
530    }
531
532    #[test]
533    fn test_from_value_float() {
534        let v = 42.5f64.to_value();
535        let f = f64::from_value(&v, &types::float64()).unwrap();
536        assert_eq!(f, 42.5);
537
538        let v = "Infinity".to_string().to_value();
539        let f = f64::from_value(&v, &types::float64()).unwrap();
540        assert_eq!(f, f64::INFINITY);
541
542        let v = "invalid float".to_string().to_value();
543        let err = f64::from_value(&v, &types::float64()).unwrap_err();
544        assert!(format!("{}", err).contains("invalid float literal"));
545    }
546
547    #[test]
548    fn test_from_value_bool() {
549        let v = true.to_value();
550        let b = bool::from_value(&v, &types::bool()).unwrap();
551        assert!(b);
552    }
553
554    #[test]
555    fn test_from_value_array() {
556        // String array
557        let str_array = vec!["one".to_string(), "two".to_string()];
558        let v = str_array.to_value();
559        let res = Vec::<String>::from_value(&v, &types::array(types::string()))
560            .expect("parsed string array");
561        assert_eq!(res, str_array);
562
563        // Int array
564        let int_array = vec![42i64, 100i64];
565        let v = int_array.to_value();
566        let res =
567            Vec::<i64>::from_value(&v, &types::array(types::int64())).expect("parsed int array");
568        assert_eq!(res, int_array);
569
570        // Bool array
571        let bool_array = vec![true, false];
572        let v = bool_array.to_value();
573        let res =
574            Vec::<bool>::from_value(&v, &types::array(types::bool())).expect("parsed bool array");
575        assert_eq!(res, bool_array);
576
577        // Float array
578        let float_array = vec![9.9f64, -2.5f64];
579        let v = float_array.to_value();
580        let res = Vec::<f64>::from_value(&v, &types::array(types::float64()))
581            .expect("parsed float array");
582        assert_eq!(res, float_array);
583
584        // Empty array
585        let empty_array: Vec<f64> = vec![];
586        let v = empty_array.to_value();
587        let res = Vec::<f64>::from_value(&v, &types::array(types::float64()))
588            .expect("parsed empty array");
589        assert_eq!(res, empty_array);
590
591        // Array with nulls
592        let opt_array: Vec<Option<i64>> = vec![Some(42), None, Some(100)];
593        let v = opt_array.to_value();
594        let res = Vec::<Option<i64>>::from_value(&v, &types::array(types::int64()))
595            .expect("parsed optional array");
596        assert_eq!(res, opt_array);
597
598        // Null array entirely
599        let null_array: Option<Vec<i64>> = None;
600        let v = null_array.to_value();
601        let res = Option::<Vec<i64>>::from_value(&v, &types::array(types::int64()))
602            .expect("parsed null array");
603        assert_eq!(res, null_array);
604
605        // Wrong TypeCode test
606        let err = Vec::<i64>::from_value(&int_array.to_value(), &types::int64()).unwrap_err();
607        assert!(format!("{}", err).contains("expected List"));
608
609        // Invalid array element values
610        let err = Vec::<i64>::from_value(&str_array.to_value(), &types::array(types::int64()))
611            .unwrap_err();
612        assert!(format!("{}", err).contains("cannot convert value, source="));
613    }
614
615    #[test]
616    fn test_from_value_bytes() {
617        let bytes: Vec<u8> = vec![1, 2, 3];
618        let v = bytes.to_value();
619        let b = Vec::<u8>::from_value(&v, &types::bytes()).unwrap();
620        assert_eq!(b, bytes);
621
622        let v = "invalid base64".to_string().to_value();
623        let err = Vec::<u8>::from_value(&v, &types::bytes()).unwrap_err();
624        assert!(format!("{}", err).contains("cannot convert value"));
625    }
626
627    #[test]
628    fn test_from_value_decimal() {
629        let d = Decimal::from_str_exact("123.456").unwrap();
630        let v = d.to_value();
631        let res = Decimal::from_value(&v, &types::numeric()).unwrap();
632        assert_eq!(res, d);
633
634        let v = "invalid decimal".to_string().to_value();
635        let err = Decimal::from_value(&v, &types::numeric()).unwrap_err();
636        assert!(format!("{}", err).contains("cannot convert value"));
637    }
638
639    #[test]
640    fn test_from_value_date() {
641        let d = Date::from_calendar_date(2023, time::Month::October, 27).unwrap();
642        let v = d.to_value();
643        let res = Date::from_value(&v, &types::date()).unwrap();
644        assert_eq!(res, d);
645
646        let v = "invalid date".to_string().to_value();
647        let err = Date::from_value(&v, &types::date()).unwrap_err();
648        assert!(format!("{}", err).contains("cannot convert value"));
649    }
650
651    #[test]
652    fn test_from_value_timestamp() {
653        let dt = OffsetDateTime::parse(
654            "2023-10-27T10:00:00Z",
655            &time::format_description::well_known::Rfc3339,
656        )
657        .unwrap();
658        let v = dt.to_value();
659        let res = OffsetDateTime::from_value(&v, &types::timestamp()).unwrap();
660        assert_eq!(res, dt);
661
662        let v = "invalid timestamp".to_string().to_value();
663        let err = OffsetDateTime::from_value(&v, &types::timestamp()).unwrap_err();
664        assert!(format!("{}", err).contains("cannot convert value"));
665    }
666
667    #[test]
668    fn test_from_value_null() {
669        let v = Option::<i32>::None.to_value();
670        let res = Option::<i32>::from_value(&v, &types::int64()).unwrap();
671        assert_eq!(res, None);
672
673        let v = Option::<i32>::None.to_value();
674        let err = i32::from_value(&v, &types::int64()).unwrap_err();
675        assert!(format!("{}", err).contains("expected non-null value, got null"));
676    }
677    #[test]
678    fn test_from_value_system_time() {
679        let dt = OffsetDateTime::parse(
680            "2023-10-27T10:00:00Z",
681            &time::format_description::well_known::Rfc3339,
682        )
683        .unwrap();
684        let system_time: SystemTime = dt.into();
685        let v = system_time.to_value();
686        let res = SystemTime::from_value(&v, &types::timestamp()).unwrap();
687        let res_dt: OffsetDateTime = res.into();
688        assert_eq!(res_dt, dt);
689
690        let v = "invalid timestamp".to_string().to_value();
691        let err = SystemTime::from_value(&v, &types::timestamp()).unwrap_err();
692        assert!(format!("{}", err).contains("cannot convert value"));
693    }
694
695    #[test]
696    fn test_from_value_wkt_timestamp() {
697        let dt = OffsetDateTime::parse(
698            "2023-10-27T10:00:00Z",
699            &time::format_description::well_known::Rfc3339,
700        )
701        .expect("valid date time parsing");
702        let wkt_ts = wkt::Timestamp::try_from(dt).expect("valid wkt timestamp conversion");
703        let v = dt.to_value();
704        let res = wkt::Timestamp::from_value(&v, &types::timestamp())
705            .expect("valid wkt timestamp decoding");
706        assert_eq!(res, wkt_ts);
707
708        let v = "invalid timestamp".to_string().to_value();
709        let err = wkt::Timestamp::from_value(&v, &types::timestamp()).unwrap_err();
710        assert!(format!("{}", err).contains("cannot convert value"));
711    }
712
713    #[test]
714    fn test_from_value_type_mismatch() {
715        let v = Decimal::from(42).to_value();
716        let err = Decimal::from_value(&v, &types::int64()).unwrap_err();
717        assert!(format!("{}", err).contains("expected String, got String"));
718
719        let v = SystemTime::now().to_value();
720        let err = SystemTime::from_value(&v, &types::string()).unwrap_err();
721        assert!(format!("{}", err).contains("expected String, got String")); // This might require adjustment as logic changed. In `SystemTime::from_value`, we check TypeCode first.
722
723        let v = OffsetDateTime::now_utc().to_value();
724        let err = OffsetDateTime::from_value(&v, &types::string()).unwrap_err();
725        assert!(format!("{}", err).contains("expected String, got String"));
726
727        let v = Date::from_calendar_date(2023, time::Month::October, 27)
728            .unwrap()
729            .to_value();
730        let err = Date::from_value(&v, &types::string()).unwrap_err();
731        assert!(format!("{}", err).contains("expected String, got String"));
732
733        let v = vec![1u8].to_value();
734        let err = Vec::<u8>::from_value(&v, &types::string()).unwrap_err();
735        assert!(format!("{}", err).contains("expected String, got String"));
736    }
737
738    #[test]
739    fn test_from_value_wrong_kind() {
740        let v_bool = true.to_value();
741        let err = String::from_value(&v_bool, &types::string()).unwrap_err();
742        assert!(format!("{}", err).contains("expected String, got Bool"));
743
744        let v_string = "hello".to_value();
745        let err = i64::from_value(&v_string, &types::int64()).unwrap_err();
746        assert!(format!("{}", err).contains("cannot convert value"));
747
748        let v_struct = crate::value::Value(prost_types::Value {
749            kind: Some(prost_types::value::Kind::StructValue(
750                prost_types::Struct::default(),
751            )),
752        });
753        let err = i64::from_value(&v_struct, &types::int64()).unwrap_err();
754        assert!(format!("{}", err).contains("expected String, got Struct"));
755
756        let err = f64::from_value(&v_bool, &types::float64()).unwrap_err();
757        assert!(format!("{}", err).contains("expected Number, got Bool"));
758
759        let err = bool::from_value(&v_string, &types::bool()).unwrap_err();
760        assert!(format!("{}", err).contains("expected Bool, got String"));
761    }
762
763    #[test]
764    fn test_from_value_null_errors() {
765        let v_null = Option::<i32>::None.to_value();
766
767        let err = String::from_value(&v_null, &types::string()).unwrap_err();
768        assert!(format!("{}", err).contains("expected non-null value, got null"));
769
770        let err = i64::from_value(&v_null, &types::int64()).unwrap_err();
771        assert!(format!("{}", err).contains("expected non-null value, got null"));
772
773        let err = f64::from_value(&v_null, &types::float64()).unwrap_err();
774        assert!(format!("{}", err).contains("expected non-null value, got null"));
775
776        let err = f32::from_value(&v_null, &types::float32()).unwrap_err();
777        assert!(format!("{}", err).contains("expected non-null value, got null"));
778
779        let err = bool::from_value(&v_null, &types::bool()).unwrap_err();
780        assert!(format!("{}", err).contains("expected non-null value, got null"));
781
782        let err = Decimal::from_value(&v_null, &types::numeric()).unwrap_err();
783        assert!(format!("{}", err).contains("expected non-null value, got null"));
784
785        let err = SystemTime::from_value(&v_null, &types::timestamp()).unwrap_err();
786        assert!(format!("{}", err).contains("expected non-null value, got null"));
787
788        let err = OffsetDateTime::from_value(&v_null, &types::timestamp()).unwrap_err();
789        assert!(format!("{}", err).contains("expected non-null value, got null"));
790
791        let err = Date::from_value(&v_null, &types::date()).unwrap_err();
792        assert!(format!("{}", err).contains("expected non-null value, got null"));
793
794        let err = Vec::<u8>::from_value(&v_null, &types::bytes()).unwrap_err();
795        assert!(format!("{}", err).contains("expected non-null value, got null"));
796    }
797
798    #[test]
799    fn test_from_value_option_missing_kind() {
800        let v = crate::value::Value(prost_types::Value { kind: None });
801        let err = Option::<i32>::from_value(&v, &types::int64()).unwrap_err();
802        assert!(format!("{}", err).contains("expected String, got Null"));
803    }
804
805    // ── JSON value conversion tests ──────────────────────────────────────
806
807    #[test]
808    fn test_from_value_json_primitives() {
809        // String → JSON string
810        let v = "hello".to_value();
811        let j = JsonValue::from_value(&v, &types::string()).unwrap();
812        assert_eq!(j, JsonValue::String("hello".to_string()));
813
814        // INT64 is string-encoded on the wire → stays as JSON string
815        // (preserves full i64 range without precision loss)
816        let v = 42i64.to_value();
817        let j = JsonValue::from_value(&v, &types::int64()).unwrap();
818        assert_eq!(j, JsonValue::String("42".to_string()));
819
820        // Bool → JSON bool
821        let v = true.to_value();
822        let j = JsonValue::from_value(&v, &types::bool()).unwrap();
823        assert_eq!(j, JsonValue::Bool(true));
824
825        // Float64 → JSON number
826        let v = 1.5f64.to_value();
827        let j = JsonValue::from_value(&v, &types::float64()).unwrap();
828        assert_eq!(j, serde_json::json!(1.5));
829
830        // Null → JSON null
831        let v: Option<i64> = None;
832        let j = JsonValue::from_value(&v.to_value(), &types::int64()).unwrap();
833        assert_eq!(j, JsonValue::Null);
834
835        // Missing kind → JSON null
836        let v = crate::value::Value(prost_types::Value { kind: None });
837        let j = JsonValue::from_value(&v, &types::string()).unwrap();
838        assert_eq!(j, JsonValue::Null);
839    }
840
841    #[test]
842    fn test_from_value_json_string_array() {
843        let str_array = vec!["a".to_string(), "b".to_string()];
844        let v = str_array.to_value();
845        let j = JsonValue::from_value(&v, &types::array(types::string())).unwrap();
846        assert_eq!(j, serde_json::json!(["a", "b"]));
847    }
848
849    #[test]
850    fn test_from_value_json_int_array() {
851        // INT64 array — values are string-encoded
852        let int_array = vec![10i64, 20i64];
853        let v = int_array.to_value();
854        let j = JsonValue::from_value(&v, &types::array(types::int64())).unwrap();
855        assert_eq!(j, serde_json::json!(["10", "20"]));
856    }
857
858    #[test]
859    fn test_from_value_json_positional_struct() {
860        // Type: STRUCT<name STRING, age INT64>
861        let struct_type = types::create_type(TypeCode::Struct);
862        let mut inner: mdl::Type = struct_type.0;
863        inner.struct_type = Some(Box::new(mdl::StructType {
864            fields: vec![
865                mdl::struct_type::Field::new()
866                    .set_name("name")
867                    .set_type(mdl::Type {
868                        code: mdl::TypeCode::String,
869                        ..Default::default()
870                    }),
871                mdl::struct_type::Field::new()
872                    .set_name("age")
873                    .set_type(mdl::Type {
874                        code: mdl::TypeCode::Int64,
875                        ..Default::default()
876                    }),
877            ],
878            _unknown_fields: Default::default(),
879        }));
880        let spanner_type = Type(inner);
881
882        // Wire value: positional ListValue ["Alice", "30"]
883        let v = crate::value::Value(prost_types::Value {
884            kind: Some(prost_types::value::Kind::ListValue(
885                prost_types::ListValue {
886                    values: vec![
887                        prost_types::Value {
888                            kind: Some(prost_types::value::Kind::StringValue("Alice".to_string())),
889                        },
890                        prost_types::Value {
891                            kind: Some(prost_types::value::Kind::StringValue("30".to_string())),
892                        },
893                    ],
894                },
895            )),
896        });
897
898        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
899        assert_eq!(j, serde_json::json!({"name": "Alice", "age": "30"}));
900    }
901
902    #[test]
903    fn test_from_value_json_array_of_structs() {
904        // Type: ARRAY<STRUCT<a STRING, b INT64>>
905        let elem_struct = mdl::Type {
906            code: mdl::TypeCode::Struct,
907            struct_type: Some(Box::new(mdl::StructType {
908                fields: vec![
909                    mdl::struct_type::Field::new()
910                        .set_name("a")
911                        .set_type(mdl::Type {
912                            code: mdl::TypeCode::String,
913                            ..Default::default()
914                        }),
915                    mdl::struct_type::Field::new()
916                        .set_name("b")
917                        .set_type(mdl::Type {
918                            code: mdl::TypeCode::Int64,
919                            ..Default::default()
920                        }),
921                ],
922                _unknown_fields: Default::default(),
923            })),
924            ..Default::default()
925        };
926        let array_type = mdl::Type {
927            code: mdl::TypeCode::Array,
928            array_element_type: Some(Box::new(elem_struct)),
929            ..Default::default()
930        };
931        let spanner_type = Type(array_type);
932
933        // Wire: [[x, 1], [y, 2]] — positional structs inside an array
934        let v = crate::value::Value(prost_types::Value {
935            kind: Some(prost_types::value::Kind::ListValue(
936                prost_types::ListValue {
937                    values: vec![
938                        prost_types::Value {
939                            kind: Some(prost_types::value::Kind::ListValue(
940                                prost_types::ListValue {
941                                    values: vec![
942                                        prost_types::Value {
943                                            kind: Some(prost_types::value::Kind::StringValue(
944                                                "x".to_string(),
945                                            )),
946                                        },
947                                        prost_types::Value {
948                                            kind: Some(prost_types::value::Kind::StringValue(
949                                                "1".to_string(),
950                                            )),
951                                        },
952                                    ],
953                                },
954                            )),
955                        },
956                        prost_types::Value {
957                            kind: Some(prost_types::value::Kind::ListValue(
958                                prost_types::ListValue {
959                                    values: vec![
960                                        prost_types::Value {
961                                            kind: Some(prost_types::value::Kind::StringValue(
962                                                "y".to_string(),
963                                            )),
964                                        },
965                                        prost_types::Value {
966                                            kind: Some(prost_types::value::Kind::StringValue(
967                                                "2".to_string(),
968                                            )),
969                                        },
970                                    ],
971                                },
972                            )),
973                        },
974                    ],
975                },
976            )),
977        });
978
979        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
980        assert_eq!(
981            j,
982            serde_json::json!([
983                {"a": "x", "b": "1"},
984                {"a": "y", "b": "2"},
985            ])
986        );
987    }
988
989    #[test]
990    fn test_from_value_json_named_struct() {
991        // Type: STRUCT<name STRING>
992        let struct_type_mdl =
993            mdl::Type {
994                code: mdl::TypeCode::Struct,
995                struct_type: Some(Box::new(mdl::StructType {
996                    fields: vec![mdl::struct_type::Field::new().set_name("name").set_type(
997                        mdl::Type {
998                            code: mdl::TypeCode::String,
999                            ..Default::default()
1000                        },
1001                    )],
1002                    _unknown_fields: Default::default(),
1003                })),
1004                ..Default::default()
1005            };
1006        let spanner_type = Type(struct_type_mdl);
1007
1008        // Wire: named StructValue (rare but valid)
1009        let mut s = prost_types::Struct::default();
1010        s.fields.insert(
1011            "name".to_string(),
1012            prost_types::Value {
1013                kind: Some(prost_types::value::Kind::StringValue("Alice".to_string())),
1014            },
1015        );
1016        let v = crate::value::Value(prost_types::Value {
1017            kind: Some(prost_types::value::Kind::StructValue(s)),
1018        });
1019
1020        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1021        assert_eq!(j, serde_json::json!({"name": "Alice"}));
1022    }
1023
1024    #[test]
1025    fn test_from_value_json_named_struct_missing_fields_become_null() {
1026        // Type declares 2 fields but wire StructValue only has 1
1027        let struct_type_mdl = mdl::Type {
1028            code: mdl::TypeCode::Struct,
1029            struct_type: Some(Box::new(mdl::StructType {
1030                fields: vec![
1031                    mdl::struct_type::Field::new()
1032                        .set_name("present")
1033                        .set_type(mdl::Type {
1034                            code: mdl::TypeCode::String,
1035                            ..Default::default()
1036                        }),
1037                    mdl::struct_type::Field::new()
1038                        .set_name("absent")
1039                        .set_type(mdl::Type {
1040                            code: mdl::TypeCode::Int64,
1041                            ..Default::default()
1042                        }),
1043                ],
1044                _unknown_fields: Default::default(),
1045            })),
1046            ..Default::default()
1047        };
1048        let spanner_type = Type(struct_type_mdl);
1049
1050        // Wire: named StructValue with only "present" field
1051        let mut s = prost_types::Struct::default();
1052        s.fields.insert(
1053            "present".to_string(),
1054            prost_types::Value {
1055                kind: Some(prost_types::value::Kind::StringValue("here".to_string())),
1056            },
1057        );
1058        let v = crate::value::Value(prost_types::Value {
1059            kind: Some(prost_types::value::Kind::StructValue(s)),
1060        });
1061
1062        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1063        assert_eq!(j, serde_json::json!({"present": "here", "absent": null}));
1064    }
1065
1066    #[test]
1067    fn test_from_value_json_spanner_json_column() {
1068        // Spanner JSON column: value arrives as a StringValue containing JSON text
1069        let json_str = r#"{"key": "value", "nested": [1, 2, 3]}"#;
1070        let v = crate::value::Value(prost_types::Value {
1071            kind: Some(prost_types::value::Kind::StringValue(json_str.to_string())),
1072        });
1073
1074        let j = JsonValue::from_value(&v, &types::json()).unwrap();
1075        assert_eq!(j, serde_json::json!({"key": "value", "nested": [1, 2, 3]}));
1076    }
1077
1078    #[test]
1079    fn test_from_value_json_nested_struct_in_struct() {
1080        // Type: STRUCT<outer_field STRING, inner STRUCT<x INT64, y BOOL>>
1081        let inner_struct_type = mdl::Type {
1082            code: mdl::TypeCode::Struct,
1083            struct_type: Some(Box::new(mdl::StructType {
1084                fields: vec![
1085                    mdl::struct_type::Field::new()
1086                        .set_name("x")
1087                        .set_type(mdl::Type {
1088                            code: mdl::TypeCode::Int64,
1089                            ..Default::default()
1090                        }),
1091                    mdl::struct_type::Field::new()
1092                        .set_name("y")
1093                        .set_type(mdl::Type {
1094                            code: mdl::TypeCode::Bool,
1095                            ..Default::default()
1096                        }),
1097                ],
1098                _unknown_fields: Default::default(),
1099            })),
1100            ..Default::default()
1101        };
1102
1103        let outer_type = mdl::Type {
1104            code: mdl::TypeCode::Struct,
1105            struct_type: Some(Box::new(mdl::StructType {
1106                fields: vec![
1107                    mdl::struct_type::Field::new()
1108                        .set_name("outer_field")
1109                        .set_type(mdl::Type {
1110                            code: mdl::TypeCode::String,
1111                            ..Default::default()
1112                        }),
1113                    mdl::struct_type::Field::new()
1114                        .set_name("inner")
1115                        .set_type(inner_struct_type),
1116                ],
1117                _unknown_fields: Default::default(),
1118            })),
1119            ..Default::default()
1120        };
1121        let spanner_type = Type(outer_type);
1122
1123        // Wire: positional list ["hello", ["42", true]]
1124        let v = crate::value::Value(prost_types::Value {
1125            kind: Some(prost_types::value::Kind::ListValue(
1126                prost_types::ListValue {
1127                    values: vec![
1128                        prost_types::Value {
1129                            kind: Some(prost_types::value::Kind::StringValue("hello".to_string())),
1130                        },
1131                        prost_types::Value {
1132                            kind: Some(prost_types::value::Kind::ListValue(
1133                                prost_types::ListValue {
1134                                    values: vec![
1135                                        prost_types::Value {
1136                                            kind: Some(prost_types::value::Kind::StringValue(
1137                                                "42".to_string(),
1138                                            )),
1139                                        },
1140                                        prost_types::Value {
1141                                            kind: Some(prost_types::value::Kind::BoolValue(true)),
1142                                        },
1143                                    ],
1144                                },
1145                            )),
1146                        },
1147                    ],
1148                },
1149            )),
1150        });
1151
1152        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1153        assert_eq!(
1154            j,
1155            serde_json::json!({"outer_field": "hello", "inner": {"x": "42", "y": true}})
1156        );
1157    }
1158
1159    #[test]
1160    fn test_from_value_json_null_in_struct() {
1161        // Type: STRUCT<name STRING, value INT64>
1162        let struct_type_mdl = mdl::Type {
1163            code: mdl::TypeCode::Struct,
1164            struct_type: Some(Box::new(mdl::StructType {
1165                fields: vec![
1166                    mdl::struct_type::Field::new()
1167                        .set_name("name")
1168                        .set_type(mdl::Type {
1169                            code: mdl::TypeCode::String,
1170                            ..Default::default()
1171                        }),
1172                    mdl::struct_type::Field::new()
1173                        .set_name("value")
1174                        .set_type(mdl::Type {
1175                            code: mdl::TypeCode::Int64,
1176                            ..Default::default()
1177                        }),
1178                ],
1179                _unknown_fields: Default::default(),
1180            })),
1181            ..Default::default()
1182        };
1183        let spanner_type = Type(struct_type_mdl);
1184
1185        // Wire: ["test", null]
1186        let v = crate::value::Value(prost_types::Value {
1187            kind: Some(prost_types::value::Kind::ListValue(
1188                prost_types::ListValue {
1189                    values: vec![
1190                        prost_types::Value {
1191                            kind: Some(prost_types::value::Kind::StringValue("test".to_string())),
1192                        },
1193                        prost_types::Value {
1194                            kind: Some(prost_types::value::Kind::NullValue(0)),
1195                        },
1196                    ],
1197                },
1198            )),
1199        });
1200
1201        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1202        assert_eq!(j, serde_json::json!({"name": "test", "value": null}));
1203    }
1204
1205    #[test]
1206    fn test_from_value_json_nan_becomes_null() {
1207        // NumberValue representations
1208        let v = crate::value::Value(prost_types::Value {
1209            kind: Some(prost_types::value::Kind::NumberValue(f64::NAN)),
1210        });
1211        let j = JsonValue::from_value(&v, &types::float64()).unwrap();
1212        assert_eq!(j, JsonValue::Null);
1213
1214        let v = crate::value::Value(prost_types::Value {
1215            kind: Some(prost_types::value::Kind::NumberValue(f64::INFINITY)),
1216        });
1217        let j = JsonValue::from_value(&v, &types::float64()).unwrap();
1218        assert_eq!(j, JsonValue::Null);
1219
1220        let v = crate::value::Value(prost_types::Value {
1221            kind: Some(prost_types::value::Kind::NumberValue(f64::NEG_INFINITY)),
1222        });
1223        let j = JsonValue::from_value(&v, &types::float64()).unwrap();
1224        assert_eq!(j, JsonValue::Null);
1225
1226        // StringValue representations (as sent by Spanner wire format)
1227        let v = crate::value::Value(prost_types::Value {
1228            kind: Some(prost_types::value::Kind::StringValue("NaN".to_string())),
1229        });
1230        let j = JsonValue::from_value(&v, &types::float64()).unwrap();
1231        assert_eq!(j, JsonValue::Null);
1232
1233        let v = crate::value::Value(prost_types::Value {
1234            kind: Some(prost_types::value::Kind::StringValue(
1235                "Infinity".to_string(),
1236            )),
1237        });
1238        let j = JsonValue::from_value(&v, &types::float64()).unwrap();
1239        assert_eq!(j, JsonValue::Null);
1240
1241        let v = crate::value::Value(prost_types::Value {
1242            kind: Some(prost_types::value::Kind::StringValue(
1243                "-Infinity".to_string(),
1244            )),
1245        });
1246        let j = JsonValue::from_value(&v, &types::float64()).unwrap();
1247        assert_eq!(j, JsonValue::Null);
1248    }
1249
1250    #[test]
1251    fn test_from_value_json_option_wrapping() {
1252        // Option<JsonValue> for a non-null value
1253        let v = "hello".to_value();
1254        let j = Option::<JsonValue>::from_value(&v, &types::string()).unwrap();
1255        assert_eq!(j, Some(JsonValue::String("hello".to_string())));
1256
1257        // Option<JsonValue> for a null value
1258        let v: Option<String> = None;
1259        let j = Option::<JsonValue>::from_value(&v.to_value(), &types::string()).unwrap();
1260        assert_eq!(j, None);
1261    }
1262
1263    #[test]
1264    fn test_from_value_json_empty_struct() {
1265        // Type: STRUCT<> (zero fields)
1266        let struct_type_mdl = mdl::Type {
1267            code: mdl::TypeCode::Struct,
1268            struct_type: Some(Box::new(mdl::StructType {
1269                fields: vec![],
1270                _unknown_fields: Default::default(),
1271            })),
1272            ..Default::default()
1273        };
1274        let spanner_type = Type(struct_type_mdl);
1275
1276        // Wire: empty positional list
1277        let v = crate::value::Value(prost_types::Value {
1278            kind: Some(prost_types::value::Kind::ListValue(
1279                prost_types::ListValue { values: vec![] },
1280            )),
1281        });
1282
1283        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1284        assert_eq!(j, serde_json::json!({}));
1285    }
1286
1287    #[test]
1288    fn test_from_value_json_unnamed_fields() {
1289        // Type: STRUCT with unnamed fields (empty string names)
1290        // This is valid in Spanner for SELECT expressions without aliases.
1291        let struct_type_mdl = mdl::Type {
1292            code: mdl::TypeCode::Struct,
1293            struct_type: Some(Box::new(mdl::StructType {
1294                fields: vec![
1295                    mdl::struct_type::Field::new()
1296                        .set_name("")
1297                        .set_type(mdl::Type {
1298                            code: mdl::TypeCode::String,
1299                            ..Default::default()
1300                        }),
1301                    mdl::struct_type::Field::new()
1302                        .set_name("")
1303                        .set_type(mdl::Type {
1304                            code: mdl::TypeCode::Int64,
1305                            ..Default::default()
1306                        }),
1307                ],
1308                _unknown_fields: Default::default(),
1309            })),
1310            ..Default::default()
1311        };
1312        let spanner_type = Type(struct_type_mdl);
1313
1314        // Wire: positional values
1315        let v = crate::value::Value(prost_types::Value {
1316            kind: Some(prost_types::value::Kind::ListValue(
1317                prost_types::ListValue {
1318                    values: vec![
1319                        prost_types::Value {
1320                            kind: Some(prost_types::value::Kind::StringValue("val".to_string())),
1321                        },
1322                        prost_types::Value {
1323                            kind: Some(prost_types::value::Kind::StringValue("99".to_string())),
1324                        },
1325                    ],
1326                },
1327            )),
1328        });
1329
1330        // Unnamed fields map to empty-string keys; last write wins for duplicates.
1331        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1332        assert!(j.is_object());
1333        // With duplicate empty keys, the map retains the last inserted value
1334        assert_eq!(
1335            j.as_object().unwrap().get("").unwrap(),
1336            &serde_json::json!("99")
1337        );
1338    }
1339
1340    #[test]
1341    fn test_from_value_json_vec_composition() {
1342        // Vec<JsonValue> uses the existing Vec<T>: FromValue impl
1343        let str_array = vec!["one".to_string(), "two".to_string()];
1344        let v = str_array.to_value();
1345        let res = Vec::<JsonValue>::from_value(&v, &types::array(types::string())).unwrap();
1346        assert_eq!(res.len(), 2);
1347        assert_eq!(res[0], JsonValue::String("one".to_string()));
1348        assert_eq!(res[1], JsonValue::String("two".to_string()));
1349    }
1350
1351    #[test]
1352    fn test_from_value_json_struct_without_metadata() {
1353        // StructValue wire format without type metadata — preserves raw field names
1354        let mut s = prost_types::Struct::default();
1355        s.fields.insert(
1356            "raw_field".to_string(),
1357            prost_types::Value {
1358                kind: Some(prost_types::value::Kind::BoolValue(true)),
1359            },
1360        );
1361        let v = crate::value::Value(prost_types::Value {
1362            kind: Some(prost_types::value::Kind::StructValue(s)),
1363        });
1364
1365        // Pass default type (no struct_type metadata)
1366        let j = JsonValue::from_value(&v, &Type::default()).unwrap();
1367        assert_eq!(j, serde_json::json!({"raw_field": true}));
1368    }
1369
1370    #[test]
1371    fn test_from_value_json_list_without_type_info() {
1372        // ListValue with no type context — falls back to plain array
1373        let v = crate::value::Value(prost_types::Value {
1374            kind: Some(prost_types::value::Kind::ListValue(
1375                prost_types::ListValue {
1376                    values: vec![
1377                        prost_types::Value {
1378                            kind: Some(prost_types::value::Kind::StringValue("a".to_string())),
1379                        },
1380                        prost_types::Value {
1381                            kind: Some(prost_types::value::Kind::BoolValue(false)),
1382                        },
1383                    ],
1384                },
1385            )),
1386        });
1387
1388        let j = JsonValue::from_value(&v, &Type::default()).unwrap();
1389        assert_eq!(j, serde_json::json!(["a", false]));
1390    }
1391
1392    #[test]
1393    fn test_from_value_json_invalid_json_column() {
1394        // Spanner JSON column with invalid JSON text → error
1395        let v = crate::value::Value(prost_types::Value {
1396            kind: Some(prost_types::value::Kind::StringValue(
1397                "not valid json{".to_string(),
1398            )),
1399        });
1400
1401        let err = JsonValue::from_value(&v, &types::json()).unwrap_err();
1402        assert!(format!("{}", err).contains("cannot convert value"));
1403    }
1404
1405    #[test]
1406    fn test_from_value_json_missing_positional_fields_become_null() {
1407        // Type declares 3 fields but wire only has 1 value
1408        let struct_type_mdl = mdl::Type {
1409            code: mdl::TypeCode::Struct,
1410            struct_type: Some(Box::new(mdl::StructType {
1411                fields: vec![
1412                    mdl::struct_type::Field::new()
1413                        .set_name("a")
1414                        .set_type(mdl::Type {
1415                            code: mdl::TypeCode::String,
1416                            ..Default::default()
1417                        }),
1418                    mdl::struct_type::Field::new()
1419                        .set_name("b")
1420                        .set_type(mdl::Type {
1421                            code: mdl::TypeCode::Int64,
1422                            ..Default::default()
1423                        }),
1424                    mdl::struct_type::Field::new()
1425                        .set_name("c")
1426                        .set_type(mdl::Type {
1427                            code: mdl::TypeCode::Bool,
1428                            ..Default::default()
1429                        }),
1430                ],
1431                _unknown_fields: Default::default(),
1432            })),
1433            ..Default::default()
1434        };
1435        let spanner_type = Type(struct_type_mdl);
1436
1437        // Wire: only one value present
1438        let v = crate::value::Value(prost_types::Value {
1439            kind: Some(prost_types::value::Kind::ListValue(
1440                prost_types::ListValue {
1441                    values: vec![prost_types::Value {
1442                        kind: Some(prost_types::value::Kind::StringValue("only_a".to_string())),
1443                    }],
1444                },
1445            )),
1446        });
1447
1448        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1449        assert_eq!(j, serde_json::json!({"a": "only_a", "b": null, "c": null}));
1450    }
1451
1452    #[test]
1453    fn test_from_value_json_array_of_json_columns() {
1454        // Type: ARRAY<JSON>
1455        let json_type = mdl::Type {
1456            code: mdl::TypeCode::Json,
1457            ..Default::default()
1458        };
1459        let array_type = mdl::Type {
1460            code: mdl::TypeCode::Array,
1461            array_element_type: Some(Box::new(json_type)),
1462            ..Default::default()
1463        };
1464        let spanner_type = Type(array_type);
1465
1466        // Wire: array of JSON strings
1467        let v = crate::value::Value(prost_types::Value {
1468            kind: Some(prost_types::value::Kind::ListValue(
1469                prost_types::ListValue {
1470                    values: vec![
1471                        prost_types::Value {
1472                            kind: Some(prost_types::value::Kind::StringValue(
1473                                r#"{"x":1}"#.to_string(),
1474                            )),
1475                        },
1476                        prost_types::Value {
1477                            kind: Some(prost_types::value::Kind::StringValue(
1478                                r#"{"y":2}"#.to_string(),
1479                            )),
1480                        },
1481                    ],
1482                },
1483            )),
1484        });
1485
1486        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1487        assert_eq!(j, serde_json::json!([{"x": 1}, {"y": 2}]));
1488    }
1489
1490    #[test]
1491    fn test_from_value_json_nested_array_in_struct() {
1492        // Type: STRUCT<tags ARRAY<STRING>, id INT64>
1493        let struct_type_mdl = mdl::Type {
1494            code: mdl::TypeCode::Struct,
1495            struct_type: Some(Box::new(mdl::StructType {
1496                fields: vec![
1497                    mdl::struct_type::Field::new()
1498                        .set_name("tags")
1499                        .set_type(mdl::Type {
1500                            code: mdl::TypeCode::Array,
1501                            array_element_type: Some(Box::new(mdl::Type {
1502                                code: mdl::TypeCode::String,
1503                                ..Default::default()
1504                            })),
1505                            ..Default::default()
1506                        }),
1507                    mdl::struct_type::Field::new()
1508                        .set_name("id")
1509                        .set_type(mdl::Type {
1510                            code: mdl::TypeCode::Int64,
1511                            ..Default::default()
1512                        }),
1513                ],
1514                _unknown_fields: Default::default(),
1515            })),
1516            ..Default::default()
1517        };
1518        let spanner_type = Type(struct_type_mdl);
1519
1520        // Wire: [["foo", "bar"], "42"]
1521        let v = crate::value::Value(prost_types::Value {
1522            kind: Some(prost_types::value::Kind::ListValue(
1523                prost_types::ListValue {
1524                    values: vec![
1525                        prost_types::Value {
1526                            kind: Some(prost_types::value::Kind::ListValue(
1527                                prost_types::ListValue {
1528                                    values: vec![
1529                                        prost_types::Value {
1530                                            kind: Some(prost_types::value::Kind::StringValue(
1531                                                "foo".to_string(),
1532                                            )),
1533                                        },
1534                                        prost_types::Value {
1535                                            kind: Some(prost_types::value::Kind::StringValue(
1536                                                "bar".to_string(),
1537                                            )),
1538                                        },
1539                                    ],
1540                                },
1541                            )),
1542                        },
1543                        prost_types::Value {
1544                            kind: Some(prost_types::value::Kind::StringValue("42".to_string())),
1545                        },
1546                    ],
1547                },
1548            )),
1549        });
1550
1551        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1552        assert_eq!(j, serde_json::json!({"tags": ["foo", "bar"], "id": "42"}));
1553    }
1554
1555    #[test]
1556    fn test_from_value_json_recursion_depth_limit() {
1557        // Build a deeply nested ListValue (65 levels deep) to exceed MAX_RECURSION_DEPTH
1558        let mut inner = prost_types::Value {
1559            kind: Some(prost_types::value::Kind::BoolValue(true)),
1560        };
1561        for _ in 0..65 {
1562            inner = prost_types::Value {
1563                kind: Some(prost_types::value::Kind::ListValue(
1564                    prost_types::ListValue {
1565                        values: vec![inner],
1566                    },
1567                )),
1568            };
1569        }
1570        let v = crate::value::Value(inner);
1571
1572        let err = JsonValue::from_value(&v, &Type::default()).unwrap_err();
1573        assert!(format!("{}", err).contains("nesting depth exceeded"));
1574    }
1575
1576    #[test]
1577    fn test_from_value_json_array_without_element_type() {
1578        // Type: ARRAY but array_element_type is None
1579        let array_type = mdl::Type {
1580            code: mdl::TypeCode::Array,
1581            array_element_type: None,
1582            ..Default::default()
1583        };
1584        let spanner_type = Type(array_type);
1585
1586        // Wire: array of strings
1587        let v = crate::value::Value(prost_types::Value {
1588            kind: Some(prost_types::value::Kind::ListValue(
1589                prost_types::ListValue {
1590                    values: vec![prost_types::Value {
1591                        kind: Some(prost_types::value::Kind::StringValue("hello".to_string())),
1592                    }],
1593                },
1594            )),
1595        });
1596
1597        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1598        assert_eq!(j, serde_json::json!(["hello"]));
1599    }
1600
1601    #[test]
1602    fn test_from_value_json_struct_with_missing_field_type() {
1603        // Type: STRUCT where field "a" has no type metadata
1604        let struct_type_mdl = mdl::Type {
1605            code: mdl::TypeCode::Struct,
1606            struct_type: Some(Box::new(mdl::StructType {
1607                fields: vec![
1608                    mdl::struct_type::Field::new().set_name("a"), // type is None
1609                ],
1610                _unknown_fields: Default::default(),
1611            })),
1612            ..Default::default()
1613        };
1614        let spanner_type = Type(struct_type_mdl);
1615
1616        // Wire: positional list ["hello"]
1617        let v = crate::value::Value(prost_types::Value {
1618            kind: Some(prost_types::value::Kind::ListValue(
1619                prost_types::ListValue {
1620                    values: vec![prost_types::Value {
1621                        kind: Some(prost_types::value::Kind::StringValue("hello".to_string())),
1622                    }],
1623                },
1624            )),
1625        });
1626
1627        let j = JsonValue::from_value(&v, &spanner_type).unwrap();
1628        assert_eq!(j, serde_json::json!({"a": "hello"}));
1629    }
1630}