1use indexmap::IndexMap;
2use serde_json;
3use std::collections::HashMap;
4use std::fmt;
5#[cfg(feature = "async-runtime")]
6use std::future::Future;
7#[cfg(feature = "async-runtime")]
8use std::pin::Pin;
9use std::sync::atomic::{AtomicU64, Ordering};
10use std::sync::{Arc, Mutex};
11
12use crate::ast::{Param, Stmt};
13#[cfg(feature = "vm")]
14use crate::bytecode::Chunk;
15#[cfg(feature = "async-runtime")]
16use crate::error::IonError;
17
18static NEXT_FN_ID: AtomicU64 = AtomicU64::new(1);
19
20#[derive(Debug, Clone)]
22pub enum Value {
23 Int(i64),
24 Float(f64),
25 Bool(bool),
26 Str(String),
27 Bytes(Vec<u8>),
28 List(Vec<Value>),
29 Dict(IndexMap<String, Value>),
30 Tuple(Vec<Value>),
31 Option(Option<Box<Value>>),
32 Result(Result<Box<Value>, Box<Value>>),
33 Fn(IonFn),
34 BuiltinFn(String, BuiltinFn),
35 BuiltinClosure(String, BuiltinClosureFn),
42 #[cfg(feature = "async-runtime")]
46 AsyncBuiltinClosure(String, AsyncBuiltinClosureFn),
47 #[cfg(feature = "async-runtime")]
49 AsyncTask(crate::async_runtime::AsyncTask),
50 #[cfg(feature = "async-runtime")]
52 AsyncChannelSender(crate::async_runtime::NativeChannelSender),
53 #[cfg(feature = "async-runtime")]
55 AsyncChannelReceiver(crate::async_runtime::NativeChannelReceiver),
56 Set(Vec<Value>),
58 HostStruct {
60 type_name: String,
61 fields: IndexMap<String, Value>,
62 },
63 HostEnum {
65 enum_name: String,
66 variant: String,
67 data: Vec<Value>,
68 },
69 #[cfg(all(feature = "legacy-threaded-concurrency", not(feature = "async-runtime")))]
71 Task(std::sync::Arc<dyn crate::async_rt::TaskHandle>),
72 #[cfg(all(feature = "legacy-threaded-concurrency", not(feature = "async-runtime")))]
74 Channel(crate::async_rt::ChannelEnd),
75 Cell(Arc<Mutex<Value>>),
77 Range {
79 start: i64,
80 end: i64,
81 inclusive: bool,
82 },
83 Unit,
84}
85
86#[derive(Debug, Clone)]
88pub struct IonFn {
89 pub fn_id: u64,
90 pub name: String,
91 pub params: Vec<Param>,
92 pub body: Vec<Stmt>,
93 pub captures: HashMap<String, Value>,
95}
96
97impl IonFn {
98 pub fn new(
99 name: String,
100 params: Vec<Param>,
101 body: Vec<Stmt>,
102 captures: HashMap<String, Value>,
103 ) -> Self {
104 Self {
105 fn_id: NEXT_FN_ID.fetch_add(1, Ordering::Relaxed),
106 name,
107 params,
108 body,
109 captures,
110 }
111 }
112}
113
114#[cfg(feature = "vm")]
116pub type FnChunkCache = HashMap<u64, Chunk>;
117
118pub type BuiltinFn = fn(&[Value]) -> Result<Value, String>;
120pub type BuiltinClosure = dyn Fn(&[Value]) -> Result<Value, String> + Send + Sync;
121#[cfg(feature = "async-runtime")]
122pub type BoxIonFuture = Pin<Box<dyn Future<Output = Result<Value, IonError>> + 'static>>;
123#[cfg(feature = "async-runtime")]
124pub type AsyncBuiltinClosure = dyn Fn(Vec<Value>) -> BoxIonFuture + 'static;
125#[cfg(feature = "async-runtime")]
126pub type AsyncHostFn = dyn Fn(Vec<Value>) -> HostCallResult + 'static;
127
128#[cfg(feature = "async-runtime")]
130pub enum HostCallResult {
131 Ready(Result<Value, IonError>),
132 Pending(BoxIonFuture),
133}
134
135#[derive(Clone)]
138pub struct BuiltinClosureFn(pub Arc<BuiltinClosure>);
139
140impl fmt::Debug for BuiltinClosureFn {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 write!(f, "<closure>")
143 }
144}
145
146impl BuiltinClosureFn {
147 pub fn new<F>(func: F) -> Self
148 where
149 F: Fn(&[Value]) -> Result<Value, String> + Send + Sync + 'static,
150 {
151 Self(Arc::new(func))
152 }
153
154 pub fn call(&self, args: &[Value]) -> Result<Value, String> {
155 (self.0)(args)
156 }
157}
158
159#[cfg(feature = "async-runtime")]
162#[derive(Clone)]
163pub struct AsyncBuiltinClosureFn(pub Arc<AsyncBuiltinClosure>);
164
165#[cfg(feature = "async-runtime")]
166impl fmt::Debug for AsyncBuiltinClosureFn {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 write!(f, "<async closure>")
169 }
170}
171
172#[cfg(feature = "async-runtime")]
173impl AsyncBuiltinClosureFn {
174 pub fn new<F, Fut>(func: F) -> Self
175 where
176 F: Fn(Vec<Value>) -> Fut + 'static,
177 Fut: Future<Output = Result<Value, IonError>> + 'static,
178 {
179 Self(Arc::new(move |args| Box::pin(func(args))))
180 }
181
182 pub fn call(&self, args: Vec<Value>) -> BoxIonFuture {
183 (self.0)(args)
184 }
185}
186
187impl Value {
188 pub fn type_name(&self) -> &'static str {
189 match self {
190 Value::Int(_) => ion_static_str!("int"),
191 Value::Float(_) => ion_static_str!("float"),
192 Value::Bool(_) => ion_static_str!("bool"),
193 Value::Str(_) => ion_static_str!("string"),
194 Value::Bytes(_) => ion_static_str!("bytes"),
195 Value::List(_) => ion_static_str!("list"),
196 Value::Dict(_) => ion_static_str!("dict"),
197 Value::Tuple(_) => ion_static_str!("tuple"),
198 Value::Set(_) => ion_static_str!("set"),
199 Value::Option(_) => ion_static_str!("Option"),
200 Value::Result(_) => ion_static_str!("Result"),
201 Value::Fn(_) => ion_static_str!("fn"),
202 Value::BuiltinFn(_, _) => ion_static_str!("builtin_fn"),
203 Value::BuiltinClosure(_, _) => ion_static_str!("builtin_fn"),
204 #[cfg(feature = "async-runtime")]
205 Value::AsyncBuiltinClosure(_, _) => ion_static_str!("async_builtin_fn"),
206 #[cfg(feature = "async-runtime")]
207 Value::AsyncTask(_) => ion_static_str!("AsyncTask"),
208 #[cfg(feature = "async-runtime")]
209 Value::AsyncChannelSender(_) => ion_static_str!("AsyncChannelSender"),
210 #[cfg(feature = "async-runtime")]
211 Value::AsyncChannelReceiver(_) => ion_static_str!("AsyncChannelReceiver"),
212 Value::HostStruct { .. } => ion_static_str!("struct"),
213 Value::HostEnum { .. } => ion_static_str!("enum"),
214 #[cfg(all(feature = "legacy-threaded-concurrency", not(feature = "async-runtime")))]
215 Value::Task(_) => ion_static_str!("Task"),
216 #[cfg(all(feature = "legacy-threaded-concurrency", not(feature = "async-runtime")))]
217 Value::Channel(_) => ion_static_str!("Channel"),
218 Value::Cell(_) => ion_static_str!("cell"),
219 Value::Range { .. } => ion_static_str!("range"),
220 Value::Unit => ion_static_str!("()"),
221 }
222 }
223
224 pub fn is_truthy(&self) -> bool {
225 match self {
226 Value::Bool(b) => *b,
227 Value::Int(n) => *n != 0,
228 Value::Bytes(b) => !b.is_empty(),
229 Value::Option(None) => false,
230 Value::Unit => false,
231 _ => true,
232 }
233 }
234
235 pub fn as_int(&self) -> Option<i64> {
236 match self {
237 Value::Int(n) => Some(*n),
238 _ => None,
239 }
240 }
241
242 pub fn as_float(&self) -> Option<f64> {
243 match self {
244 Value::Float(n) => Some(*n),
245 Value::Int(n) => Some(*n as f64),
246 _ => None,
247 }
248 }
249
250 pub fn as_str(&self) -> Option<&str> {
251 match self {
252 Value::Str(s) => Some(s),
253 _ => None,
254 }
255 }
256
257 pub fn as_bool(&self) -> Option<bool> {
258 match self {
259 Value::Bool(b) => Some(*b),
260 _ => None,
261 }
262 }
263
264 pub fn range_to_list(start: i64, end: i64, inclusive: bool) -> Vec<Value> {
266 if inclusive {
267 (start..=end).map(Value::Int).collect()
268 } else {
269 (start..end).map(Value::Int).collect()
270 }
271 }
272
273 pub fn range_len(start: i64, end: i64, inclusive: bool) -> i64 {
275 if inclusive {
276 (end - start + 1).max(0)
277 } else {
278 (end - start).max(0)
279 }
280 }
281}
282
283impl fmt::Display for Value {
284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285 match self {
286 Value::Int(n) => write!(f, "{}", n),
287 Value::Float(n) => {
288 if *n == n.floor() && n.is_finite() {
289 write!(f, "{:.1}", n)
290 } else {
291 write!(f, "{}", n)
292 }
293 }
294 Value::Bool(b) => write!(f, "{}", b),
295 Value::Str(s) => write!(f, "{}", s),
296 Value::Bytes(bytes) => {
297 write!(f, "b\"")?;
298 for &b in bytes {
299 match b {
300 b'\\' => write!(f, "\\\\")?,
301 b'"' => write!(f, "\\\"")?,
302 b'\n' => write!(f, "\\n")?,
303 b'\t' => write!(f, "\\t")?,
304 b'\r' => write!(f, "\\r")?,
305 0x20..=0x7e => write!(f, "{}", b as char)?,
306 _ => write!(f, "\\x{:02x}", b)?,
307 }
308 }
309 write!(f, "\"")
310 }
311 Value::List(items) => {
312 write!(f, "[")?;
313 for (i, item) in items.iter().enumerate() {
314 if i > 0 {
315 write!(f, ", ")?;
316 }
317 write!(f, "{}", item)?;
318 }
319 write!(f, "]")
320 }
321 Value::Dict(map) => {
322 write!(f, "#{{")?;
323 for (i, (k, v)) in map.iter().enumerate() {
324 if i > 0 {
325 write!(f, ", ")?;
326 }
327 write!(f, "\"{}\": {}", k, v)?;
328 }
329 write!(f, "}}")
330 }
331 Value::Tuple(items) => {
332 write!(f, "(")?;
333 for (i, item) in items.iter().enumerate() {
334 if i > 0 {
335 write!(f, ", ")?;
336 }
337 write!(f, "{}", item)?;
338 }
339 if items.len() == 1 {
340 write!(f, ",")?;
341 }
342 write!(f, ")")
343 }
344 Value::Set(items) => {
345 write!(f, "set{{")?;
346 for (i, item) in items.iter().enumerate() {
347 if i > 0 {
348 write!(f, ", ")?;
349 }
350 write!(f, "{}", item)?;
351 }
352 write!(f, "}}")
353 }
354 Value::Option(opt) => match opt {
355 Some(v) => write!(f, "Some({})", v),
356 None => write!(f, "None"),
357 },
358 Value::Result(res) => match res {
359 Ok(v) => write!(f, "Ok({})", v),
360 Err(e) => write!(f, "Err({})", e),
361 },
362 Value::Fn(func) => write!(f, "<fn {}>", func.name),
363 Value::BuiltinFn(name, _) => write!(f, "<builtin {}>", name),
364 Value::BuiltinClosure(name, _) => write!(f, "<builtin {}>", name),
365 #[cfg(feature = "async-runtime")]
366 Value::AsyncBuiltinClosure(name, _) => write!(f, "<async builtin {}>", name),
367 #[cfg(feature = "async-runtime")]
368 Value::AsyncTask(_) => write!(f, "<AsyncTask>"),
369 #[cfg(feature = "async-runtime")]
370 Value::AsyncChannelSender(_) => write!(f, "<AsyncChannelTx>"),
371 #[cfg(feature = "async-runtime")]
372 Value::AsyncChannelReceiver(_) => write!(f, "<AsyncChannelRx>"),
373 #[cfg(all(feature = "legacy-threaded-concurrency", not(feature = "async-runtime")))]
374 Value::Task(_) => write!(f, "<Task>"),
375 #[cfg(all(feature = "legacy-threaded-concurrency", not(feature = "async-runtime")))]
376 Value::Channel(ch) => match ch {
377 crate::async_rt::ChannelEnd::Sender(_) => write!(f, "<ChannelTx>"),
378 crate::async_rt::ChannelEnd::Receiver(_) => write!(f, "<ChannelRx>"),
379 },
380 Value::HostStruct { type_name, fields } => {
381 write!(f, "{} {{ ", type_name)?;
382 for (i, (k, v)) in fields.iter().enumerate() {
383 if i > 0 {
384 write!(f, ", ")?;
385 }
386 write!(f, "{}: {}", k, v)?;
387 }
388 write!(f, " }}")
389 }
390 Value::HostEnum {
391 enum_name,
392 variant,
393 data,
394 } => {
395 write!(f, "{}::{}", enum_name, variant)?;
396 if !data.is_empty() {
397 write!(f, "(")?;
398 for (i, v) in data.iter().enumerate() {
399 if i > 0 {
400 write!(f, ", ")?;
401 }
402 write!(f, "{}", v)?;
403 }
404 write!(f, ")")?;
405 }
406 Ok(())
407 }
408 Value::Cell(cell) => {
409 let inner = cell.lock().unwrap();
410 write!(f, "cell({})", *inner)
411 }
412 Value::Range {
413 start,
414 end,
415 inclusive,
416 } => {
417 if *inclusive {
418 write!(f, "{}..={}", start, end)
419 } else {
420 write!(f, "{}..{}", start, end)
421 }
422 }
423 Value::Unit => write!(f, "()"),
424 }
425 }
426}
427
428impl PartialEq for Value {
429 fn eq(&self, other: &Self) -> bool {
430 match (self, other) {
431 (Value::Int(a), Value::Int(b)) => a == b,
432 (Value::Float(a), Value::Float(b)) => a == b,
433 (Value::Int(a), Value::Float(b)) => (*a as f64) == *b,
434 (Value::Float(a), Value::Int(b)) => *a == (*b as f64),
435 (Value::Bool(a), Value::Bool(b)) => a == b,
436 (Value::Str(a), Value::Str(b)) => a == b,
437 (Value::Bytes(a), Value::Bytes(b)) => a == b,
438 (Value::List(a), Value::List(b)) => a == b,
439 (Value::Tuple(a), Value::Tuple(b)) => a == b,
440 (Value::Dict(a), Value::Dict(b)) => a == b,
441 (Value::Set(a), Value::Set(b)) => a.len() == b.len() && a.iter().all(|v| b.contains(v)),
442 (Value::Option(a), Value::Option(b)) => a == b,
443 (Value::Result(Ok(a)), Value::Result(Ok(b))) => a == b,
444 (Value::Result(Err(a)), Value::Result(Err(b))) => a == b,
445 (
446 Value::HostStruct {
447 type_name: a_name,
448 fields: a_fields,
449 },
450 Value::HostStruct {
451 type_name: b_name,
452 fields: b_fields,
453 },
454 ) => a_name == b_name && a_fields == b_fields,
455 (
456 Value::HostEnum {
457 enum_name: a_en,
458 variant: a_v,
459 data: a_d,
460 },
461 Value::HostEnum {
462 enum_name: b_en,
463 variant: b_v,
464 data: b_d,
465 },
466 ) => a_en == b_en && a_v == b_v && a_d == b_d,
467 (Value::Cell(a), Value::Cell(b)) => Arc::ptr_eq(a, b),
468 (
469 Value::Range {
470 start: s1,
471 end: e1,
472 inclusive: i1,
473 },
474 Value::Range {
475 start: s2,
476 end: e2,
477 inclusive: i2,
478 },
479 ) => s1 == s2 && e1 == e2 && i1 == i2,
480 (Value::Unit, Value::Unit) => true,
481 (Value::Option(None), Value::Unit) => false,
482 #[cfg(feature = "async-runtime")]
483 (Value::AsyncTask(a), Value::AsyncTask(b)) => a.ptr_eq(b),
484 #[cfg(feature = "async-runtime")]
485 (Value::AsyncChannelSender(a), Value::AsyncChannelSender(b)) => a.ptr_eq(b),
486 #[cfg(feature = "async-runtime")]
487 (Value::AsyncChannelReceiver(a), Value::AsyncChannelReceiver(b)) => a.ptr_eq(b),
488 _ => false,
490 }
491 }
492}
493
494impl Value {
497 pub fn to_json(&self) -> serde_json::Value {
499 match self {
500 Value::Int(n) => serde_json::Value::Number((*n).into()),
501 Value::Float(n) => serde_json::Number::from_f64(*n)
502 .map(serde_json::Value::Number)
503 .unwrap_or(serde_json::Value::Null),
504 Value::Bool(b) => serde_json::Value::Bool(*b),
505 Value::Str(s) => serde_json::Value::String(s.clone()),
506 Value::List(items) => {
507 serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
508 }
509 Value::Dict(map) => {
510 let obj: serde_json::Map<String, serde_json::Value> =
511 map.iter().map(|(k, v)| (k.clone(), v.to_json())).collect();
512 serde_json::Value::Object(obj)
513 }
514 Value::Tuple(items) => {
515 serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
516 }
517 Value::Set(items) => {
518 serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
519 }
520 Value::Option(Some(v)) => v.to_json(),
521 Value::Option(None) | Value::Unit => serde_json::Value::Null,
522 Value::Result(Ok(v)) => v.to_json(),
523 Value::Result(Err(v)) => {
524 let mut map = serde_json::Map::new();
525 map.insert("error".to_string(), v.to_json());
526 serde_json::Value::Object(map)
527 }
528 Value::HostStruct { fields, .. } => {
529 let obj: serde_json::Map<String, serde_json::Value> = fields
530 .iter()
531 .map(|(k, v)| (k.clone(), v.to_json()))
532 .collect();
533 serde_json::Value::Object(obj)
534 }
535 Value::HostEnum {
536 enum_name,
537 variant,
538 data,
539 } => {
540 let mut map = serde_json::Map::new();
541 map.insert(
542 "_type".to_string(),
543 serde_json::Value::String(format!("{}::{}", enum_name, variant)),
544 );
545 if !data.is_empty() {
546 map.insert(
547 "data".to_string(),
548 serde_json::Value::Array(data.iter().map(|v| v.to_json()).collect()),
549 );
550 }
551 serde_json::Value::Object(map)
552 }
553 #[cfg(all(feature = "legacy-threaded-concurrency", not(feature = "async-runtime")))]
554 Value::Task(_) | Value::Channel(_) => serde_json::Value::Null,
555 Value::Cell(cell) => cell.lock().unwrap().to_json(),
556 Value::Bytes(b) => {
557 let hex: String = b.iter().map(|byte| format!("{:02x}", byte)).collect();
558 serde_json::Value::String(hex)
559 }
560 Value::Range {
561 start,
562 end,
563 inclusive,
564 } => serde_json::Value::Array(
565 Value::range_to_list(*start, *end, *inclusive)
566 .iter()
567 .map(|v| v.to_json())
568 .collect(),
569 ),
570 Value::Fn(_) | Value::BuiltinFn(_, _) | Value::BuiltinClosure(_, _) => {
571 serde_json::Value::Null
572 }
573 #[cfg(feature = "async-runtime")]
574 Value::AsyncBuiltinClosure(_, _)
575 | Value::AsyncTask(_)
576 | Value::AsyncChannelSender(_)
577 | Value::AsyncChannelReceiver(_) => serde_json::Value::Null,
578 }
579 }
580
581 #[cfg(feature = "msgpack")]
583 pub fn to_msgpack(&self) -> Result<Vec<u8>, String> {
584 let mp = self.to_msgpack_value();
585 let mut buf = Vec::new();
586 rmpv::encode::write_value(&mut buf, &mp)
587 .map_err(|e| format!("{}{}", ion_str!("msgpack_encode error: "), e))?;
588 Ok(buf)
589 }
590
591 #[cfg(feature = "msgpack")]
593 pub fn from_msgpack(data: &[u8]) -> Result<Value, String> {
594 let mut cursor = std::io::Cursor::new(data);
595 let mp = rmpv::decode::read_value(&mut cursor)
596 .map_err(|e| format!("{}{}", ion_str!("msgpack_decode error: "), e))?;
597 Ok(Self::from_msgpack_value(mp))
598 }
599
600 #[cfg(feature = "msgpack")]
601 fn to_msgpack_value(&self) -> rmpv::Value {
602 match self {
603 Value::Int(n) => rmpv::Value::Integer((*n).into()),
604 Value::Float(n) => rmpv::Value::F64(*n),
605 Value::Bool(b) => rmpv::Value::Boolean(*b),
606 Value::Str(s) => rmpv::Value::String(s.clone().into()),
607 Value::Bytes(b) => rmpv::Value::Binary(b.clone()),
608 Value::List(items) => {
609 rmpv::Value::Array(items.iter().map(|v| v.to_msgpack_value()).collect())
610 }
611 Value::Dict(map) => {
612 let pairs: Vec<(rmpv::Value, rmpv::Value)> = map
613 .iter()
614 .map(|(k, v)| (rmpv::Value::String(k.clone().into()), v.to_msgpack_value()))
615 .collect();
616 rmpv::Value::Map(pairs)
617 }
618 Value::Tuple(items) => {
619 rmpv::Value::Array(items.iter().map(|v| v.to_msgpack_value()).collect())
620 }
621 Value::Set(items) => {
622 rmpv::Value::Array(items.iter().map(|v| v.to_msgpack_value()).collect())
623 }
624 Value::Option(Some(v)) => v.to_msgpack_value(),
625 Value::Option(None) | Value::Unit => rmpv::Value::Nil,
626 Value::Result(Ok(v)) => v.to_msgpack_value(),
627 Value::Result(Err(v)) => {
628 let pairs = vec![(rmpv::Value::String("error".into()), v.to_msgpack_value())];
629 rmpv::Value::Map(pairs)
630 }
631 Value::HostStruct { fields, .. } => {
632 let pairs: Vec<(rmpv::Value, rmpv::Value)> = fields
633 .iter()
634 .map(|(k, v)| (rmpv::Value::String(k.clone().into()), v.to_msgpack_value()))
635 .collect();
636 rmpv::Value::Map(pairs)
637 }
638 Value::HostEnum {
639 enum_name,
640 variant,
641 data,
642 } => {
643 let mut pairs = vec![(
644 rmpv::Value::String("_type".into()),
645 rmpv::Value::String(format!("{}::{}", enum_name, variant).into()),
646 )];
647 if !data.is_empty() {
648 pairs.push((
649 rmpv::Value::String("data".into()),
650 rmpv::Value::Array(data.iter().map(|v| v.to_msgpack_value()).collect()),
651 ));
652 }
653 rmpv::Value::Map(pairs)
654 }
655 #[cfg(all(feature = "legacy-threaded-concurrency", not(feature = "async-runtime")))]
656 Value::Task(_) | Value::Channel(_) => rmpv::Value::Nil,
657 Value::Cell(cell) => cell.lock().unwrap().to_msgpack_value(),
658 Value::Range {
659 start,
660 end,
661 inclusive,
662 } => rmpv::Value::Array(
663 Value::range_to_list(*start, *end, *inclusive)
664 .iter()
665 .map(|v| v.to_msgpack_value())
666 .collect(),
667 ),
668 Value::Fn(_) | Value::BuiltinFn(_, _) | Value::BuiltinClosure(_, _) => rmpv::Value::Nil,
669 #[cfg(feature = "async-runtime")]
670 Value::AsyncBuiltinClosure(_, _)
671 | Value::AsyncTask(_)
672 | Value::AsyncChannelSender(_)
673 | Value::AsyncChannelReceiver(_) => rmpv::Value::Nil,
674 }
675 }
676
677 #[cfg(feature = "msgpack")]
678 fn from_msgpack_value(mp: rmpv::Value) -> Value {
679 match mp {
680 rmpv::Value::Nil => Value::Option(None),
681 rmpv::Value::Boolean(b) => Value::Bool(b),
682 rmpv::Value::Integer(n) => {
683 if let Some(i) = n.as_i64() {
684 Value::Int(i)
685 } else if let Some(u) = n.as_u64() {
686 Value::Int(u as i64)
687 } else {
688 Value::Int(0)
689 }
690 }
691 rmpv::Value::F32(f) => Value::Float(f as f64),
692 rmpv::Value::F64(f) => Value::Float(f),
693 rmpv::Value::String(s) => Value::Str(s.into_str().unwrap_or_default().to_string()),
694 rmpv::Value::Binary(b) => Value::Bytes(b),
695 rmpv::Value::Array(arr) => {
696 Value::List(arr.into_iter().map(Self::from_msgpack_value).collect())
697 }
698 rmpv::Value::Map(pairs) => {
699 let dict: IndexMap<String, Value> = pairs
700 .into_iter()
701 .filter_map(|(k, v)| {
702 let key = match k {
703 rmpv::Value::String(s) => s.into_str().map(|s| s.to_string()),
704 _ => None,
705 };
706 key.map(|k| (k, Self::from_msgpack_value(v)))
707 })
708 .collect();
709 Value::Dict(dict)
710 }
711 rmpv::Value::Ext(_, data) => Value::Bytes(data),
712 }
713 }
714
715 pub fn from_json(json: serde_json::Value) -> Value {
717 match json {
718 serde_json::Value::Null => Value::Option(None),
719 serde_json::Value::Bool(b) => Value::Bool(b),
720 serde_json::Value::Number(n) => {
721 if let Some(i) = n.as_i64() {
722 Value::Int(i)
723 } else if let Some(f) = n.as_f64() {
724 Value::Float(f)
725 } else {
726 Value::Int(0)
727 }
728 }
729 serde_json::Value::String(s) => Value::Str(s),
730 serde_json::Value::Array(arr) => {
731 Value::List(arr.into_iter().map(Value::from_json).collect())
732 }
733 serde_json::Value::Object(map) => {
734 let dict: IndexMap<String, Value> = map
735 .into_iter()
736 .map(|(k, v)| (k, Value::from_json(v)))
737 .collect();
738 Value::Dict(dict)
739 }
740 }
741 }
742}