1use rust_decimal::prelude::ToPrimitive;
13use schemars::JsonSchema;
14use thiserror::Error as ThisError;
15
16pub use rust_decimal::Decimal;
17
18pub(crate) mod value_type;
19pub use value_type::keys;
20
21pub(crate) const TOKEN: &str = "$V";
22
23mod de;
24pub use de::const_bytes::ConstBytes;
25
26mod ser;
27
28pub mod crud;
29pub mod macros;
30
31pub mod with;
32
33#[cfg(feature = "bincode")]
34pub mod bincode_impl;
35
36pub mod decimal;
38#[cfg(feature = "solana-keypair")]
39#[deprecated]
40pub mod keypair;
41#[cfg(feature = "solana-pubkey")]
42pub mod pubkey;
43#[cfg(feature = "solana-signature")]
44pub mod signature;
45
46pub fn from_value<T>(value: Value) -> Result<T, Error>
65where
66 T: for<'de> serde::Deserialize<'de>,
67{
68 T::deserialize(value)
69}
70
71pub fn from_map<T>(map: Map) -> Result<T, Error>
90where
91 T: for<'de> serde::Deserialize<'de>,
92{
93 T::deserialize(Value::Map(map))
94}
95
96pub fn to_value<T>(t: &T) -> Result<Value, Error>
109where
110 T: serde::Serialize,
111{
112 t.serialize(ser::Serializer)
113}
114
115pub fn to_map<T>(t: &T) -> Result<Map, Error>
126where
127 T: serde::Serialize,
128{
129 to_value(t).and_then(|v| match v {
130 Value::Map(map) => Ok(map),
131 _ => Err(Error::ExpectedMap),
132 })
133}
134
135pub type HashMap<K, V> = indexmap::IndexMap<K, V>;
137
138pub type Key = String;
140
141pub type Map = self::HashMap<Key, Value>;
142
143#[derive(Clone, PartialEq, Default)]
240pub enum Value {
242 #[default]
247 Null,
248 String(String),
255 Bool(bool),
260 U64(u64),
268 I64(i64),
273 F64(f64),
282 Decimal(Decimal),
289 U128(u128),
294 I128(i128),
299 B32([u8; 32]),
306 B64([u8; 64]),
313 Bytes(bytes::Bytes),
320 Array(Vec<Self>),
335 Map(Map),
348}
349
350impl JsonSchema for Value {
351 fn schema_name() -> std::borrow::Cow<'static, str> {
352 "Value".into()
353 }
354
355 fn schema_id() -> std::borrow::Cow<'static, str> {
356 "https://schema.spaceoperator.com/value.schema.json".into()
357 }
358
359 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
360 serde_json::from_str(include_str!("../value.schema.json")).unwrap()
361 }
362}
363
364impl Value {
365 pub fn new_keypair_bs58(s: &str) -> Result<Self, Error> {
366 const KEYPAIR_LENGTH: usize = 64;
368 let mut buf = [0u8; KEYPAIR_LENGTH];
369 let size = bs58::decode(s).into(&mut buf)?;
370 if size != KEYPAIR_LENGTH {
371 return Err(Error::InvalidLenght {
372 need: KEYPAIR_LENGTH,
373 got: size,
374 });
375 }
376
377 Ok(Value::B64(buf))
378 }
379
380 pub fn normalize(self) -> Self {
381 match self {
382 Value::Null
383 | Value::String(_)
384 | Value::Bool(_)
385 | Value::U64(_)
386 | Value::I64(_)
387 | Value::F64(_)
388 | Value::B32(_)
389 | Value::B64(_)
390 | Value::Bytes(_) => self,
391 Value::Decimal(mut d) => {
392 d.normalize_assign();
393 if d.scale() == 0 {
394 Value::I128(d.to_i128().expect("always fit into i128")).normalize()
395 } else {
396 Value::Decimal(d)
397 }
398 }
399 Value::I128(i) => if i < 0 {
400 i64::try_from(i).map(Value::I64).ok()
401 } else {
402 u64::try_from(i).map(Value::U64).ok()
403 }
404 .unwrap_or(self),
405 Value::U128(u) => u64::try_from(u).map(Value::U64).unwrap_or(self),
406 Value::Array(mut a) => {
407 for v in &mut a {
408 *v = std::mem::take(v).normalize();
409 }
410 Value::Array(a)
411 }
412 Value::Map(mut m) => {
413 for v in m.values_mut() {
414 *v = std::mem::take(v).normalize();
415 }
416 Value::Map(m)
417 }
418 }
419 }
420}
421
422#[cfg(feature = "json")]
423mod json {
424 use crate::Value;
425 use rust_decimal::Decimal;
426
427 impl From<serde_json::Value> for Value {
428 fn from(value: serde_json::Value) -> Self {
429 match value {
430 serde_json::Value::Null => Value::Null,
431 serde_json::Value::Bool(b) => Value::Bool(b),
432 serde_json::Value::Number(n) => {
433 if let Some(u) = n.as_u64() {
434 Value::U64(u)
435 } else if let Some(i) = n.as_i64() {
436 if i < 0 {
437 Value::I64(i)
438 } else {
439 Value::U64(i as u64)
440 }
441 } else {
442 let s = n.to_string();
443 if let Ok(u) = s.parse::<u128>() {
444 Value::U128(u)
445 } else if let Ok(i) = s.parse::<i128>() {
446 Value::I128(i)
447 } else if let Ok(d) = s.parse::<Decimal>() {
448 Value::Decimal(d)
449 } else if let Ok(d) = Decimal::from_scientific(&s) {
450 Value::Decimal(d)
451 } else if let Ok(f) = s.parse::<f64>() {
452 Value::F64(f)
453 } else {
454 Value::String(s)
457 }
458 }
459 }
460 serde_json::Value::String(s) => Value::String(s),
461 serde_json::Value::Array(vec) => {
462 Value::Array(vec.into_iter().map(Value::from).collect())
463 }
464 serde_json::Value::Object(map) => {
465 Value::Map(map.into_iter().map(|(k, v)| (k, Value::from(v))).collect())
466 }
467 }
468 }
469 }
470
471 impl From<Value> for serde_json::Value {
472 fn from(value: Value) -> Self {
473 match value {
474 Value::Null => serde_json::Value::Null,
475 Value::String(x) => x.into(),
476 Value::Bool(x) => x.into(),
477 Value::U64(x) => x.into(),
478 Value::I64(x) => x.into(),
479 Value::F64(x) => x.into(),
480 Value::Array(x) => x.into(),
481 Value::Map(x) => x
482 .into_iter()
483 .map(|(key, value)| (key, value.into()))
484 .collect::<serde_json::Map<_, _>>()
485 .into(),
486 Value::U128(value) => value
487 .try_into()
488 .map(u64::into)
489 .unwrap_or_else(|_| (value as f64).into()),
490 Value::I128(value) => value
491 .try_into()
492 .map(i64::into)
493 .unwrap_or_else(|_| (value as f64).into()),
494 Value::Decimal(mut d) => {
495 d.normalize_assign();
496 if d.scale() == 0 {
497 if let Ok(n) = u64::try_from(d) {
498 n.into()
499 } else if let Ok(n) = i64::try_from(d) {
500 n.into()
501 } else {
502 f64::try_from(d).map_or(serde_json::Value::Null, Into::into)
503 }
504 } else {
505 f64::try_from(d).map_or(serde_json::Value::Null, Into::into)
506 }
507 }
508 Value::B32(b) => (&b[..]).into(),
509 Value::B64(b) => (&b[..]).into(),
510 Value::Bytes(b) => (&b[..]).into(),
511 }
512 }
513 }
514}
515
516impl From<String> for Value {
517 fn from(x: String) -> Self {
518 Self::String(x)
519 }
520}
521
522impl From<&str> for Value {
523 fn from(x: &str) -> Self {
524 Self::String(x.to_owned())
525 }
526}
527
528impl From<bool> for Value {
529 fn from(x: bool) -> Self {
530 Self::Bool(x)
531 }
532}
533
534impl From<u8> for Value {
535 fn from(x: u8) -> Self {
536 Self::U64(x as u64)
537 }
538}
539
540impl From<u16> for Value {
541 fn from(x: u16) -> Self {
542 Self::U64(x as u64)
543 }
544}
545
546impl From<u32> for Value {
547 fn from(x: u32) -> Self {
548 Self::U64(x as u64)
549 }
550}
551
552impl From<u64> for Value {
553 fn from(x: u64) -> Self {
554 Self::U64(x)
555 }
556}
557
558impl From<u128> for Value {
559 fn from(x: u128) -> Self {
560 Self::U128(x)
561 }
562}
563
564impl From<i8> for Value {
565 fn from(x: i8) -> Self {
566 Self::I64(x as i64)
567 }
568}
569
570impl From<i16> for Value {
571 fn from(x: i16) -> Self {
572 Self::I64(x as i64)
573 }
574}
575
576impl From<i32> for Value {
577 fn from(x: i32) -> Self {
578 Self::I64(x as i64)
579 }
580}
581
582impl From<i64> for Value {
583 fn from(x: i64) -> Self {
584 Self::I64(x)
585 }
586}
587
588impl From<i128> for Value {
589 fn from(x: i128) -> Self {
590 Self::I128(x)
591 }
592}
593
594impl From<Decimal> for Value {
595 fn from(x: Decimal) -> Self {
596 Self::Decimal(x)
597 }
598}
599
600impl From<f32> for Value {
601 fn from(x: f32) -> Self {
602 Self::F64(x as f64)
603 }
604}
605
606impl From<f64> for Value {
607 fn from(x: f64) -> Self {
608 Self::F64(x)
609 }
610}
611
612impl From<[u8; 32]> for Value {
613 fn from(x: [u8; 32]) -> Self {
614 Self::B32(x)
615 }
616}
617
618impl From<[u8; 64]> for Value {
619 fn from(x: [u8; 64]) -> Self {
620 Self::B64(x)
621 }
622}
623
624#[cfg(feature = "solana-pubkey")]
625impl From<solana_pubkey::Pubkey> for Value {
626 fn from(x: solana_pubkey::Pubkey) -> Self {
627 Self::B32(x.to_bytes())
628 }
629}
630
631#[cfg(feature = "solana-keypair")]
632impl From<solana_keypair::Keypair> for Value {
633 fn from(x: solana_keypair::Keypair) -> Self {
634 Self::B64(x.to_bytes())
635 }
636}
637
638#[cfg(feature = "solana-signature")]
639impl From<solana_signature::Signature> for Value {
640 fn from(x: solana_signature::Signature) -> Self {
641 Self::B64(x.into())
642 }
643}
644
645impl From<bytes::Bytes> for Value {
646 fn from(x: bytes::Bytes) -> Self {
647 match x.len() {
648 32 => Self::B32(<_>::try_from(&*x).unwrap()),
649 64 => Self::B64(<_>::try_from(&*x).unwrap()),
650 _ => Self::Bytes(x),
651 }
652 }
653}
654
655impl From<&[u8]> for Value {
656 fn from(x: &[u8]) -> Self {
657 match x.len() {
658 32 => Self::B32(<_>::try_from(x).unwrap()),
659 64 => Self::B64(<_>::try_from(x).unwrap()),
660 _ => Self::Bytes(bytes::Bytes::copy_from_slice(x)),
661 }
662 }
663}
664
665impl From<Vec<u8>> for Value {
666 fn from(x: Vec<u8>) -> Self {
667 match x.len() {
668 32 => Self::B32(<_>::try_from(&*x).unwrap()),
669 64 => Self::B64(<_>::try_from(&*x).unwrap()),
670 _ => Self::Bytes(x.into()),
671 }
672 }
673}
674
675impl From<Vec<Value>> for Value {
676 fn from(x: Vec<Value>) -> Self {
677 Self::Array(x)
678 }
679}
680
681impl From<Map> for Value {
682 fn from(x: Map) -> Self {
683 Self::Map(x)
684 }
685}
686
687impl std::fmt::Debug for Value {
688 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
689 match self {
690 Value::Null => f.debug_tuple("Null").finish(),
691 Value::String(x) => f.debug_tuple("String").field(x).finish(),
692 Value::Bool(x) => f.debug_tuple("Bool").field(x).finish(),
693 Value::I64(x) => f.debug_tuple("I64").field(x).finish(),
694 Value::U64(x) => f.debug_tuple("U64").field(x).finish(),
695 Value::F64(x) => f.debug_tuple("F64").field(x).finish(),
696 Value::Decimal(x) => f.debug_tuple("Decimal").field(x).finish(),
697 Value::I128(x) => f.debug_tuple("I128").field(x).finish(),
698 Value::U128(x) => f.debug_tuple("U128").field(x).finish(),
699 Value::Array(x) => f.debug_tuple("Array").field(x).finish(),
700 Value::Map(x) => f.debug_tuple("Map").field(x).finish(),
701 Value::Bytes(x) => f.debug_tuple("Bytes").field(&x.len()).finish(),
702 Value::B32(x) => f
703 .debug_tuple("B32")
704 .field(&bs58::encode(x).into_string())
705 .finish(),
706 Value::B64(x) => f
707 .debug_tuple("B64")
708 .field(&bs58::encode(x).into_string())
709 .finish(),
710 }
711 }
712}
713
714#[derive(ThisError, Debug)]
715pub enum Error {
716 #[error("{0}")]
717 Custom(String),
718 #[error("key must be a string")]
719 KeyMustBeAString,
720 #[error("invalid base58: {0}")]
721 Bs58Decode(#[from] bs58::decode::Error),
722 #[error("need length {need}, got {got}")]
723 InvalidLenght { need: usize, got: usize },
724 #[error("expected a map")]
725 ExpectedMap,
726 #[error("expected array")]
727 ExpectedArray,
728}
729
730impl serde::ser::Error for Error {
731 fn custom<T>(msg: T) -> Self
732 where
733 T: std::fmt::Display,
734 {
735 Self::Custom(msg.to_string())
736 }
737}
738
739impl serde::de::Error for Error {
740 fn custom<T>(msg: T) -> Self
741 where
742 T: std::fmt::Display,
743 {
744 Self::Custom(msg.to_string())
745 }
746}
747
748pub struct Bytes<'a>(pub &'a [u8]);
750
751impl serde::Serialize for Bytes<'_> {
752 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
753 where
754 S: serde::Serializer,
755 {
756 s.serialize_bytes(self.0)
757 }
758}
759
760pub mod default {
761 pub const fn bool_true() -> bool {
762 true
763 }
764
765 pub const fn bool_false() -> bool {
766 false
767 }
768}
769
770pub(crate) struct OptionVisitor<V>(pub(crate) V);
771
772impl<'de, V> serde::de::Visitor<'de> for OptionVisitor<V>
773where
774 V: serde::de::Visitor<'de>,
775{
776 type Value = Option<V::Value>;
777
778 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
779 formatter.write_str("optional ")?;
780 self.0.expecting(formatter)
781 }
782
783 fn visit_none<E>(self) -> Result<Self::Value, E>
784 where
785 E: serde::de::Error,
786 {
787 Ok(None)
788 }
789
790 fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
791 where
792 D: serde::Deserializer<'de>,
793 {
794 d.deserialize_any(self.0).map(Some)
795 }
796}
797
798#[cfg(test)]
799mod tests {
800 use super::*;
801 use rust_decimal_macros::dec;
802
803 #[test]
804 fn test_solana_instruction() {
805 use solana_instruction::{AccountMeta, Instruction};
806 use solana_pubkey::pubkey;
807
808 let i = Instruction::new_with_bytes(
809 pubkey!("ESxeViFP4r7THzVx9hJDkhj4HrNGSjJSFRPbGaAb97hN"),
810 &[100; 1024],
811 vec![AccountMeta {
812 pubkey: pubkey!("ESxeViFP4r7THzVx9hJDkhj4HrNGSjJSFRPbGaAb97hN"),
813 is_signer: true,
814 is_writable: false,
815 }],
816 );
817
818 let v = to_value(&i).unwrap();
819 dbg!(&v);
820
821 let i1: Instruction = from_value(v).unwrap();
822
823 assert_eq!(i, i1);
824 }
825
826 #[test]
827 fn test_json() {
828 fn t(v: Value, s: &str) {
829 assert_eq!(s, serde_json::to_string(&v).unwrap());
830 assert_eq!(v, serde_json::from_str::<Value>(s).unwrap());
831 }
832 t(Value::Null, r#"{"N":0}"#);
833 t(Value::String("hello".to_owned()), r#"{"S":"hello"}"#);
834 t(Value::U64(0), r#"{"U":"0"}"#);
835 t(Value::I64(-1), r#"{"I":"-1"}"#);
836 t(
837 Value::U128(u128::MAX),
838 r#"{"U1":"340282366920938463463374607431768211455"}"#,
839 );
840 t(
841 Value::I128(i128::MIN),
842 r#"{"I1":"-170141183460469231731687303715884105728"}"#,
843 );
844 t(Value::Bool(true), r#"{"B":true}"#);
845 t(
846 Value::Decimal(dec!(3.1415926535897932384626433833)),
847 r#"{"D":"3.1415926535897932384626433833"}"#,
848 );
849 t(
850 crate::map! {
851 "foo" => 1i64,
852 }
853 .into(),
854 r#"{"M":{"foo":{"I":"1"}}}"#,
855 );
856 t(
857 Value::Array(vec![1i64.into(), "hello".into()]),
858 r#"{"A":[{"I":"1"},{"S":"hello"}]}"#,
859 );
860 t(
861 Value::B32(
862 bs58::decode("5sNRWMrT2P3KULzW3faaktCB3k2eqHow2GBJtcsCPcg7")
863 .into_vec()
864 .unwrap()
865 .try_into()
866 .unwrap(),
867 ),
868 r#"{"B3":"5sNRWMrT2P3KULzW3faaktCB3k2eqHow2GBJtcsCPcg7"}"#,
869 );
870 t(
871 Value::B64(
872 bs58::decode("3PvNxykqBz1BzBaq2AMU4Sa3CPJGnSC9JXkyzXe33m6W7Sj4MMgsZet6YxUQdPx1fEFU79QWm6RpPRVJAyeqiNsR")
873 .into_vec()
874 .unwrap()
875 .try_into()
876 .unwrap(),
877 ),
878 r#"{"B6":"3PvNxykqBz1BzBaq2AMU4Sa3CPJGnSC9JXkyzXe33m6W7Sj4MMgsZet6YxUQdPx1fEFU79QWm6RpPRVJAyeqiNsR"}"#,
879 );
880 t(
881 Value::Bytes(bytes::Bytes::from_static(&[
882 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100,
883 ])),
884 r#"{"BY":"aGVsbG8gd29ybGQ="}"#,
885 );
886 }
887
888 #[test]
889 fn test_array_ser() {
890 #[derive(serde::Serialize)]
891 struct Output {
892 value: Value,
893 }
894
895 let mut v = crate::to_map(&Output {
896 value: Vec::from([Value::U64(1)]).into(),
897 })
898 .unwrap();
899 assert_eq!(
900 v.swap_remove("value").unwrap(),
901 Value::Array([1u64.into()].into())
902 )
903 }
904
905 #[cfg(feature = "json")]
906 #[test]
907 fn test_number_into_json() {
908 let json: serde_json::Value = Value::Decimal(dec!(15966.2)).into();
909 assert_eq!(json.as_f64().unwrap(), 15966.2);
910 }
911}