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