1use crate::error::CastError;
4use crate::schema::{LiteralValue, Schema, SchemaKind};
5use crate::value::Value;
6use indexmap::IndexMap;
7
8pub fn cast(schema: &Schema, value: &Value) -> Result<Value, CastError> {
13 match (&schema.kind, value) {
14 (SchemaKind::Null, Value::Null) => Ok(Value::Null),
15 (SchemaKind::Null, _) => Ok(Value::Null),
16
17 (SchemaKind::Bool, Value::Bool(b)) => Ok(Value::Bool(*b)),
18 (SchemaKind::Bool, v) => coerce_to_bool(v),
19
20 (SchemaKind::Int8 { minimum, maximum }, Value::Int64(n)) => {
21 let val = clamp_i64_to_i8(*n);
22 let min = minimum.unwrap_or(i8::MIN);
23 let max = maximum.unwrap_or(i8::MAX);
24 Ok(Value::Int64(clamp(val, min, max) as i64))
25 }
26 (SchemaKind::Int8 { minimum, maximum }, v) => {
27 let n = coerce_to_i64(v)?;
28 let val = clamp_i64_to_i8(n);
29 let min = minimum.unwrap_or(i8::MIN);
30 let max = maximum.unwrap_or(i8::MAX);
31 Ok(Value::Int64(clamp(val, min, max) as i64))
32 }
33
34 (SchemaKind::Int16 { minimum, maximum }, Value::Int64(n)) => {
35 let val = clamp_i64_to_i16(*n);
36 let min = minimum.unwrap_or(i16::MIN);
37 let max = maximum.unwrap_or(i16::MAX);
38 Ok(Value::Int64(clamp(val, min, max) as i64))
39 }
40 (SchemaKind::Int16 { minimum, maximum }, v) => {
41 let n = coerce_to_i64(v)?;
42 let val = clamp_i64_to_i16(n);
43 let min = minimum.unwrap_or(i16::MIN);
44 let max = maximum.unwrap_or(i16::MAX);
45 Ok(Value::Int64(clamp(val, min, max) as i64))
46 }
47
48 (SchemaKind::Int32 { minimum, maximum }, Value::Int64(n)) => {
49 let val = clamp_i64_to_i32(*n);
50 let min = minimum.unwrap_or(i32::MIN);
51 let max = maximum.unwrap_or(i32::MAX);
52 Ok(Value::Int64(clamp(val, min, max) as i64))
53 }
54 (SchemaKind::Int32 { minimum, maximum }, v) => {
55 let n = coerce_to_i64(v)?;
56 let val = clamp_i64_to_i32(n);
57 let min = minimum.unwrap_or(i32::MIN);
58 let max = maximum.unwrap_or(i32::MAX);
59 Ok(Value::Int64(clamp(val, min, max) as i64))
60 }
61
62 (SchemaKind::Int64 { minimum, maximum }, Value::Int64(n)) => {
63 let min = minimum.unwrap_or(i64::MIN);
64 let max = maximum.unwrap_or(i64::MAX);
65 Ok(Value::Int64(clamp(*n, min, max)))
66 }
67 (SchemaKind::Int64 { minimum, maximum }, v) => {
68 let n = coerce_to_i64(v)?;
69 let min = minimum.unwrap_or(i64::MIN);
70 let max = maximum.unwrap_or(i64::MAX);
71 Ok(Value::Int64(clamp(n, min, max)))
72 }
73
74 (SchemaKind::UInt8 { minimum, maximum }, Value::Int64(n)) => {
75 let val = clamp_i64_to_u8(*n);
76 let min = minimum.unwrap_or(u8::MIN);
77 let max = maximum.unwrap_or(u8::MAX);
78 Ok(Value::Int64(clamp(val, min, max) as i64))
79 }
80 (SchemaKind::UInt8 { minimum, maximum }, v) => {
81 let n = coerce_to_i64(v)?;
82 let val = clamp_i64_to_u8(n);
83 let min = minimum.unwrap_or(u8::MIN);
84 let max = maximum.unwrap_or(u8::MAX);
85 Ok(Value::Int64(clamp(val, min, max) as i64))
86 }
87
88 (SchemaKind::UInt16 { minimum, maximum }, Value::Int64(n)) => {
89 let val = clamp_i64_to_u16(*n);
90 let min = minimum.unwrap_or(u16::MIN);
91 let max = maximum.unwrap_or(u16::MAX);
92 Ok(Value::Int64(clamp(val, min, max) as i64))
93 }
94 (SchemaKind::UInt16 { minimum, maximum }, v) => {
95 let n = coerce_to_i64(v)?;
96 let val = clamp_i64_to_u16(n);
97 let min = minimum.unwrap_or(u16::MIN);
98 let max = maximum.unwrap_or(u16::MAX);
99 Ok(Value::Int64(clamp(val, min, max) as i64))
100 }
101
102 (SchemaKind::UInt32 { minimum, maximum }, Value::Int64(n)) => {
103 let val = clamp_i64_to_u32(*n);
104 let min = minimum.unwrap_or(u32::MIN);
105 let max = maximum.unwrap_or(u32::MAX);
106 Ok(Value::Int64(clamp(val, min, max) as i64))
107 }
108 (SchemaKind::UInt32 { minimum, maximum }, v) => {
109 let n = coerce_to_i64(v)?;
110 let val = clamp_i64_to_u32(n);
111 let min = minimum.unwrap_or(u32::MIN);
112 let max = maximum.unwrap_or(u32::MAX);
113 Ok(Value::Int64(clamp(val, min, max) as i64))
114 }
115
116 (SchemaKind::UInt64 { minimum, maximum }, Value::Int64(n)) => {
117 let val = (*n).max(0);
118 let min = minimum.unwrap_or(u64::MIN);
119 let max = maximum.unwrap_or(u64::MAX);
120 Ok(Value::Int64(clamp(val as u64, min, max) as i64))
121 }
122 (SchemaKind::UInt64 { minimum, maximum }, v) => {
123 let n = coerce_to_i64(v)?;
124 let val = n.max(0) as u64;
125 let min = minimum.unwrap_or(u64::MIN);
126 let max = maximum.unwrap_or(u64::MAX);
127 Ok(Value::Int64(clamp(val, min, max) as i64))
128 }
129
130 (SchemaKind::Float32 { minimum, maximum }, Value::Float64(f)) => {
131 let val = *f as f32;
132 let min = minimum.unwrap_or(f32::MIN);
133 let max = maximum.unwrap_or(f32::MAX);
134 Ok(Value::Float64(clamp_f32(val, min, max) as f64))
135 }
136 (SchemaKind::Float32 { minimum, maximum }, Value::Int64(n)) => {
137 let val = *n as f32;
138 let min = minimum.unwrap_or(f32::MIN);
139 let max = maximum.unwrap_or(f32::MAX);
140 Ok(Value::Float64(clamp_f32(val, min, max) as f64))
141 }
142 (SchemaKind::Float32 { minimum, maximum }, v) => {
143 let f = coerce_to_f64(v)?;
144 let val = f as f32;
145 let min = minimum.unwrap_or(f32::MIN);
146 let max = maximum.unwrap_or(f32::MAX);
147 Ok(Value::Float64(clamp_f32(val, min, max) as f64))
148 }
149
150 (SchemaKind::Float64 { minimum, maximum }, Value::Float64(f)) => {
151 let min = minimum.unwrap_or(f64::MIN);
152 let max = maximum.unwrap_or(f64::MAX);
153 Ok(Value::Float64(clamp_f64(*f, min, max)))
154 }
155 (SchemaKind::Float64 { minimum, maximum }, Value::Int64(n)) => {
156 let val = *n as f64;
157 let min = minimum.unwrap_or(f64::MIN);
158 let max = maximum.unwrap_or(f64::MAX);
159 Ok(Value::Float64(clamp_f64(val, min, max)))
160 }
161 (SchemaKind::Float64 { minimum, maximum }, v) => {
162 let f = coerce_to_f64(v)?;
163 let min = minimum.unwrap_or(f64::MIN);
164 let max = maximum.unwrap_or(f64::MAX);
165 Ok(Value::Float64(clamp_f64(f, min, max)))
166 }
167
168 (SchemaKind::String { .. }, Value::String(s)) => Ok(Value::String(s.clone())),
169 (SchemaKind::String { .. }, v) => Ok(Value::String(value_to_string(v))),
170
171 (SchemaKind::Bytes { .. }, Value::Bytes(b)) => Ok(Value::Bytes(b.clone())),
172 (SchemaKind::Bytes { .. }, Value::UInt8Array(b)) => Ok(Value::Bytes(b.clone())),
173 (SchemaKind::Bytes { .. }, Value::String(s)) => Ok(Value::Bytes(s.as_bytes().to_vec())),
174 (SchemaKind::Bytes { .. }, v) => Err(CastError::CannotCast(format!(
175 "cannot cast {:?} to bytes",
176 v.kind()
177 ))),
178
179 (
180 SchemaKind::Array {
181 items,
182 min_items,
183 max_items,
184 ..
185 },
186 Value::Array(arr),
187 ) => {
188 let min = min_items.unwrap_or(0);
189 let max = max_items.unwrap_or(usize::MAX);
190
191 let mut result: Vec<Value> = arr
192 .iter()
193 .take(max)
194 .map(|v| cast(items, v))
195 .collect::<Result<Vec<_>, _>>()?;
196
197 while result.len() < min {
198 result.push(super::create::create(items).map_err(|e| {
199 CastError::CannotCast(format!("cannot create default item: {}", e))
200 })?);
201 }
202
203 Ok(Value::Array(result))
204 }
205 (
206 SchemaKind::Array {
207 items, min_items, ..
208 },
209 v,
210 ) => {
211 let min = min_items.unwrap_or(0);
212 let single = cast(items, v)?;
213 let mut arr = vec![single];
214 while arr.len() < min {
215 arr.push(super::create::create(items).map_err(|e| {
216 CastError::CannotCast(format!("cannot create default item: {}", e))
217 })?);
218 }
219 Ok(Value::Array(arr))
220 }
221
222 (
223 SchemaKind::Object {
224 properties,
225 required,
226 additional_properties,
227 },
228 Value::Object(map),
229 ) => {
230 let mut result = IndexMap::new();
231
232 for field_name in required {
233 if let Some(field_schema) = properties.get(field_name) {
234 if let Some(val) = map.get(field_name) {
235 result.insert(field_name.clone(), cast(field_schema, val)?);
236 } else {
237 result.insert(
238 field_name.clone(),
239 super::create::create(field_schema).map_err(|e| {
240 CastError::CannotCast(format!("cannot create default field: {}", e))
241 })?,
242 );
243 }
244 }
245 }
246
247 if let Some(additional_schema) = additional_properties {
248 for (key, val) in map {
249 if !properties.contains_key(key) {
250 result.insert(key.clone(), cast(additional_schema, val)?);
251 }
252 }
253 }
254
255 Ok(Value::Object(result))
256 }
257 (
258 SchemaKind::Object {
259 properties,
260 required,
261 ..
262 },
263 _,
264 ) => {
265 let mut result = IndexMap::new();
266 for field_name in required {
267 if let Some(field_schema) = properties.get(field_name) {
268 result.insert(
269 field_name.clone(),
270 super::create::create(field_schema).map_err(|e| {
271 CastError::CannotCast(format!("cannot create default field: {}", e))
272 })?,
273 );
274 }
275 }
276 Ok(Value::Object(result))
277 }
278
279 (SchemaKind::Tuple { items }, Value::Array(arr)) => {
280 let mut result = Vec::with_capacity(items.len());
281 for (i, item_schema) in items.iter().enumerate() {
282 if let Some(val) = arr.get(i) {
283 result.push(cast(item_schema, val)?);
284 } else {
285 result.push(super::create::create(item_schema).map_err(|e| {
286 CastError::CannotCast(format!("cannot create tuple element: {}", e))
287 })?);
288 }
289 }
290 Ok(Value::Array(result))
291 }
292 (SchemaKind::Tuple { items }, _) => {
293 let mut result = Vec::with_capacity(items.len());
294 for item_schema in items {
295 result.push(super::create::create(item_schema).map_err(|e| {
296 CastError::CannotCast(format!("cannot create tuple element: {}", e))
297 })?);
298 }
299 Ok(Value::Array(result))
300 }
301
302 (SchemaKind::Union { any_of }, value) => {
303 for variant in any_of {
304 let casted = cast(variant, value)?;
305 if super::check::check(variant, &casted) {
306 return Ok(casted);
307 }
308 }
309 if let Some(first) = any_of.first() {
310 return cast(first, value);
311 }
312 Err(CastError::CannotCast("empty union".to_string()))
313 }
314
315 (SchemaKind::Literal { value: lit }, val) => {
316 let matches = match (lit, val) {
317 (LiteralValue::Null, Value::Null) => true,
318 (LiteralValue::Boolean(b), Value::Bool(v)) => *b == *v,
319 (LiteralValue::Number(n), Value::Int64(v)) => *n == *v,
320 (LiteralValue::Float(f), Value::Float64(v)) => (f - v).abs() < f64::EPSILON,
321 (LiteralValue::String(s), Value::String(v)) => s == v,
322 _ => false,
323 };
324 if matches {
325 Ok(val.clone())
326 } else {
327 match lit {
328 LiteralValue::Null => Ok(Value::Null),
329 LiteralValue::Boolean(b) => Ok(Value::Bool(*b)),
330 LiteralValue::Number(n) => Ok(Value::Int64(*n)),
331 LiteralValue::Float(f) => Ok(Value::Float64(*f)),
332 LiteralValue::String(s) => Ok(Value::String(s.clone())),
333 }
334 }
335 }
336
337 (SchemaKind::Enum { values }, Value::String(s)) => {
338 if values.contains(s) {
339 Ok(Value::String(s.clone()))
340 } else if let Some(first) = values.first() {
341 Ok(Value::String(first.clone()))
342 } else {
343 Err(CastError::CannotCast("empty enum".to_string()))
344 }
345 }
346 (SchemaKind::Enum { values }, _) => {
347 if let Some(first) = values.first() {
348 Ok(Value::String(first.clone()))
349 } else {
350 Err(CastError::CannotCast("empty enum".to_string()))
351 }
352 }
353
354 (SchemaKind::Ref { reference }, _) => Err(CastError::CannotCast(format!(
355 "unresolved ref: {}",
356 reference
357 ))),
358
359 (SchemaKind::Named { schema, .. }, value) => cast(schema, value),
360
361 (SchemaKind::Function { .. }, val) => Ok(val.clone()),
362 (SchemaKind::Void, _) => Ok(Value::Null),
363 (SchemaKind::Never, _) => Err(CastError::CannotCast("never type".to_string())),
364 (SchemaKind::Any, val) => Ok(val.clone()),
365 (SchemaKind::Unknown, val) => Ok(val.clone()),
366 (SchemaKind::Undefined, _) => Ok(Value::Null),
367 (SchemaKind::Recursive { schema }, value) => cast(schema, value),
368 (SchemaKind::Intersect { all_of }, value) => {
369 let mut result = value.clone();
370 for s in all_of {
371 result = cast(s, &result)?;
372 }
373 Ok(result)
374 }
375 }
376}
377
378fn coerce_to_bool(value: &Value) -> Result<Value, CastError> {
379 match value {
380 Value::Bool(b) => Ok(Value::Bool(*b)),
381 Value::Int64(n) => Ok(Value::Bool(*n != 0)),
382 Value::Float64(f) => Ok(Value::Bool(*f != 0.0)),
383 Value::String(s) => {
384 let lower = s.to_lowercase();
385 Ok(Value::Bool(
386 lower == "true" || lower == "1" || lower == "yes",
387 ))
388 }
389 Value::Null => Ok(Value::Bool(false)),
390 _ => Err(CastError::CannotCast(format!(
391 "cannot cast {:?} to bool",
392 value.kind()
393 ))),
394 }
395}
396
397fn coerce_to_i64(value: &Value) -> Result<i64, CastError> {
398 match value {
399 Value::Int64(n) => Ok(*n),
400 Value::Float64(f) => Ok(*f as i64),
401 Value::Bool(b) => Ok(if *b { 1 } else { 0 }),
402 Value::String(s) => s
403 .parse::<i64>()
404 .or_else(|_| s.parse::<f64>().map(|f| f as i64))
405 .map_err(|_| CastError::CannotCast(format!("cannot parse '{}' as number", s))),
406 _ => Err(CastError::CannotCast(format!(
407 "cannot cast {:?} to integer",
408 value.kind()
409 ))),
410 }
411}
412
413fn coerce_to_f64(value: &Value) -> Result<f64, CastError> {
414 match value {
415 Value::Float64(f) => Ok(*f),
416 Value::Int64(n) => Ok(*n as f64),
417 Value::Bool(b) => Ok(if *b { 1.0 } else { 0.0 }),
418 Value::String(s) => s
419 .parse::<f64>()
420 .map_err(|_| CastError::CannotCast(format!("cannot parse '{}' as float", s))),
421 _ => Err(CastError::CannotCast(format!(
422 "cannot cast {:?} to float",
423 value.kind()
424 ))),
425 }
426}
427
428fn value_to_string(value: &Value) -> String {
429 match value {
430 Value::Null => "null".to_string(),
431 Value::Bool(b) => b.to_string(),
432 Value::Int64(n) => n.to_string(),
433 Value::Float64(f) => f.to_string(),
434 Value::String(s) => s.clone(),
435 Value::Bytes(b) => String::from_utf8_lossy(b).to_string(),
436 Value::Array(arr) => {
437 let items: Vec<String> = arr.iter().map(value_to_string).collect();
438 format!("[{}]", items.join(", "))
439 }
440 Value::Object(map) => {
441 let items: Vec<String> = map
442 .iter()
443 .map(|(k, v)| format!("{}: {}", k, value_to_string(v)))
444 .collect();
445 format!("{{{}}}", items.join(", "))
446 }
447 _ => value.kind().to_string(),
448 }
449}
450
451fn clamp<T: Ord>(value: T, min: T, max: T) -> T {
452 if value < min {
453 min
454 } else if value > max {
455 max
456 } else {
457 value
458 }
459}
460
461fn clamp_f32(value: f32, min: f32, max: f32) -> f32 {
462 if value < min {
463 min
464 } else if value > max {
465 max
466 } else {
467 value
468 }
469}
470
471fn clamp_f64(value: f64, min: f64, max: f64) -> f64 {
472 if value < min {
473 min
474 } else if value > max {
475 max
476 } else {
477 value
478 }
479}
480
481fn clamp_i64_to_i8(n: i64) -> i8 {
482 clamp(n, i8::MIN as i64, i8::MAX as i64) as i8
483}
484
485fn clamp_i64_to_i16(n: i64) -> i16 {
486 clamp(n, i16::MIN as i64, i16::MAX as i64) as i16
487}
488
489fn clamp_i64_to_i32(n: i64) -> i32 {
490 clamp(n, i32::MIN as i64, i32::MAX as i64) as i32
491}
492
493fn clamp_i64_to_u8(n: i64) -> u8 {
494 clamp(n, 0, u8::MAX as i64) as u8
495}
496
497fn clamp_i64_to_u16(n: i64) -> u16 {
498 clamp(n, 0, u16::MAX as i64) as u16
499}
500
501fn clamp_i64_to_u32(n: i64) -> u32 {
502 clamp(n, 0, u32::MAX as i64) as u32
503}
504
505#[cfg(test)]
506mod tests {
507 use super::*;
508 use crate::builder::SchemaBuilder;
509 use crate::schema::{Schema, SchemaKind};
510
511 #[test]
512 fn test_cast_null() {
513 assert_eq!(
514 cast(&Schema::new(SchemaKind::Null), &Value::Null).unwrap(),
515 Value::Null
516 );
517 assert_eq!(
518 cast(&Schema::new(SchemaKind::Null), &Value::Int64(42)).unwrap(),
519 Value::Null
520 );
521 }
522
523 #[test]
524 fn test_cast_bool() {
525 assert_eq!(
526 cast(&Schema::new(SchemaKind::Bool), &Value::Bool(true)).unwrap(),
527 Value::Bool(true)
528 );
529 assert_eq!(
530 cast(&Schema::new(SchemaKind::Bool), &Value::Int64(1)).unwrap(),
531 Value::Bool(true)
532 );
533 assert_eq!(
534 cast(&Schema::new(SchemaKind::Bool), &Value::Int64(0)).unwrap(),
535 Value::Bool(false)
536 );
537 assert_eq!(
538 cast(
539 &Schema::new(SchemaKind::Bool),
540 &Value::String("true".to_string())
541 )
542 .unwrap(),
543 Value::Bool(true)
544 );
545 assert_eq!(
546 cast(&Schema::new(SchemaKind::Bool), &Value::Null).unwrap(),
547 Value::Bool(false)
548 );
549 }
550
551 #[test]
552 fn test_cast_int_with_bounds() {
553 let schema = Schema::new(SchemaKind::Int64 {
554 minimum: Some(10),
555 maximum: Some(20),
556 });
557 assert_eq!(cast(&schema, &Value::Int64(15)).unwrap(), Value::Int64(15));
558 assert_eq!(cast(&schema, &Value::Int64(5)).unwrap(), Value::Int64(10));
559 assert_eq!(cast(&schema, &Value::Int64(25)).unwrap(), Value::Int64(20));
560 }
561
562 #[test]
563 fn test_cast_string_to_int() {
564 assert_eq!(
565 cast(&SchemaBuilder::int64(), &Value::String("42".to_string())).unwrap(),
566 Value::Int64(42)
567 );
568 assert!(cast(
569 &SchemaBuilder::int64(),
570 &Value::String("not a number".to_string())
571 )
572 .is_err());
573 }
574
575 #[test]
576 fn test_cast_to_string() {
577 assert_eq!(
578 cast(&SchemaBuilder::string().build(), &Value::Int64(42)).unwrap(),
579 Value::String("42".to_string())
580 );
581 assert_eq!(
582 cast(&SchemaBuilder::string().build(), &Value::Bool(true)).unwrap(),
583 Value::String("true".to_string())
584 );
585 }
586
587 #[test]
588 fn test_cast_array() {
589 let schema = SchemaBuilder::array(SchemaBuilder::int64())
590 .min_items(2)
591 .max_items(3)
592 .build();
593
594 let arr = cast(&schema, &Value::Array(vec![Value::Int64(1)])).unwrap();
595 if let Value::Array(items) = arr {
596 assert_eq!(items.len(), 2);
597 assert_eq!(items[0], Value::Int64(1));
598 assert_eq!(items[1], Value::Int64(0));
599 } else {
600 panic!("Expected array");
601 }
602 }
603
604 #[test]
605 fn test_cast_object() {
606 let schema = SchemaBuilder::object()
607 .field("id", SchemaBuilder::int64())
608 .field("name", SchemaBuilder::string().build())
609 .build();
610
611 let input = Value::object()
612 .field("id", Value::String("42".to_string()))
613 .build();
614
615 let result = cast(&schema, &input).unwrap();
616 if let Value::Object(map) = result {
617 assert_eq!(map.get("id"), Some(&Value::Int64(42)));
618 assert_eq!(map.get("name"), Some(&Value::String(String::new())));
619 } else {
620 panic!("Expected object");
621 }
622 }
623
624 #[test]
625 fn test_cast_tuple() {
626 let schema = Schema::new(SchemaKind::Tuple {
627 items: vec![SchemaBuilder::int64(), SchemaBuilder::string().build()],
628 });
629
630 let input = Value::Array(vec![Value::String("42".to_string())]);
631 let result = cast(&schema, &input).unwrap();
632 assert_eq!(
633 result,
634 Value::Array(vec![Value::Int64(42), Value::String(String::new())])
635 );
636 }
637
638 #[test]
639 fn test_cast_union() {
640 let schema = SchemaBuilder::union(vec![
641 SchemaBuilder::int64(),
642 SchemaBuilder::string().build(),
643 ]);
644
645 let result = cast(&schema, &Value::Int64(42)).unwrap();
646 assert_eq!(result, Value::Int64(42));
647
648 let schema_string_first = SchemaBuilder::union(vec![
649 SchemaBuilder::string().build(),
650 SchemaBuilder::int64(),
651 ]);
652
653 let result2 = cast(&schema_string_first, &Value::Int64(42)).unwrap();
654 assert_eq!(result2, Value::String("42".to_string()));
655 }
656
657 #[test]
658 fn test_cast_literal() {
659 let schema = Schema::new(SchemaKind::Literal {
660 value: LiteralValue::String("hello".to_string()),
661 });
662
663 assert_eq!(
664 cast(&schema, &Value::String("hello".to_string())).unwrap(),
665 Value::String("hello".to_string())
666 );
667 assert_eq!(
668 cast(&schema, &Value::String("world".to_string())).unwrap(),
669 Value::String("hello".to_string())
670 );
671 }
672
673 #[test]
674 fn test_cast_enum() {
675 let schema = Schema::new(SchemaKind::Enum {
676 values: vec!["one".to_string(), "two".to_string()],
677 });
678
679 assert_eq!(
680 cast(&schema, &Value::String("one".to_string())).unwrap(),
681 Value::String("one".to_string())
682 );
683 assert_eq!(
684 cast(&schema, &Value::String("other".to_string())).unwrap(),
685 Value::String("one".to_string())
686 );
687 }
688
689 #[test]
690 fn test_cast_float_truncation() {
691 assert_eq!(
692 cast(&SchemaBuilder::int64(), &Value::Float64(3.7)).unwrap(),
693 Value::Int64(3)
694 );
695 }
696}