flow_value/
lib.rs

1//! This crate contains [`Value`], an enum representing all values that can be used as
2//! node's input and output, and utilities for working with [`Value`].
3//!
4//! Common operations:
5//! - Converting [`Value`] to Rust types.
6//! - Converting Rust types to [`Value`].
7//! - Receiving [`flow_value::Map`][Map] as node's input.
8//! - Returning [`flow_value::Map`][Map] as node's output.
9//! - Converting [`Value`] to/from JSON to use in HTTP APIs and database.
10//! - Getting and updating nested values with JSON Pointer syntax.
11
12use 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
36// custom serialize and deserialize modules
37pub mod decimal;
38#[cfg(feature = "solana-pubkey")]
39pub mod pubkey;
40#[cfg(feature = "solana-signature")]
41pub mod signature;
42
43/// Interpret a [`Value`] as an instance of type `T`
44///
45/// # Example
46///
47/// ```
48/// use solana_pubkey::{Pubkey, pubkey};
49/// use flow_value::Value;
50///
51/// #[derive(serde::Deserialize)]
52/// pub struct User {
53///     pubkey: Pubkey,
54/// }
55///
56/// let value = Value::Map(flow_value::map! {
57///     "pubkey" => pubkey!("My11111111111111111111111111111111111111111"),
58/// });
59/// flow_value::from_value::<User>(value).unwrap();
60/// ```
61pub fn from_value<T>(value: Value) -> Result<T, Error>
62where
63    T: for<'de> serde::Deserialize<'de>,
64{
65    T::deserialize(value)
66}
67
68/// Interpret a [`Map`] as an instance of type `T`
69///
70/// # Example
71///
72/// ```
73/// use solana_pubkey::{Pubkey, pubkey};
74/// use flow_value::Value;
75///
76/// #[derive(serde::Deserialize)]
77/// pub struct User {
78///     pubkey: Pubkey,
79/// }
80///
81/// let map = flow_value::map! {
82///     "pubkey" => pubkey!("My11111111111111111111111111111111111111111"),
83/// };
84/// flow_value::from_map::<User>(map).unwrap();
85/// ```
86pub 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
93/// Convert a `T` into [`Value`].
94///
95/// # Example
96///
97/// ```
98/// use solana_signature::Signature;
99/// use flow_value::Value;
100///
101/// let signature = Signature::default();
102/// let value = flow_value::to_value(&flow_value::Bytes(signature.as_ref())).unwrap();
103/// assert_eq!(value, Value::B64(signature.into()));
104/// ```
105pub fn to_value<T>(t: &T) -> Result<Value, Error>
106where
107    T: serde::Serialize,
108{
109    t.serialize(ser::Serializer)
110}
111
112/// Convert a `T` into [`Map`].
113///
114/// # Example
115///
116/// ```
117/// use flow_value::Value;
118///
119/// let map = flow_value::to_map(&serde_json::json!({"A": "B"})).unwrap();
120/// assert_eq!(map, flow_value::map! { "A" => "B" });
121/// ```
122pub 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
132/// Allow for switching HashMap implementation
133pub type HashMap<K, V> = indexmap::IndexMap<K, V>;
134
135/// Key type of [`Map`]
136pub type Key = String;
137
138pub type Map = self::HashMap<Key, Value>;
139
140/// [`Value`] represents all values that nodes can use as input and output.
141///
142/// # Data Types
143///
144/// - Scalar types:
145///     - Null: [`Value::Null`].
146///     - Boolean: [`Value::Bool`].
147///     - Numbers: [`Value::U64`], [`Value::I64`], [`Value::U128`], [`Value::I128`], [`Value::Decimal`], [`Value::F64`].
148///     - String: [`Value::String`].
149///     - Binary: [`Value::B32`], [`Value::B64`], [`Value::Bytes`].
150/// - Array: [`Value::Array`]
151/// - Map: [`Value::Map`]
152///
153/// # Node Input
154///
155/// Node receives a [`flow_value::Map`][Map] as its input. It is possible to use the map directly, but
156/// it is often preferred to convert it to structs or enums of your choice.
157///
158/// [`Value`] implements [`Deserializer`][serde::Deserializer], therefore it can be converted to
159/// any types supported by Serde. We provide 2 helpers:
160///
161/// - [`flow_value::from_value`][from_value] - [`Value`] to any `T: Deserialize`.
162/// - [`flow_value::from_map`][from_map] - [`Map`] to any `T: Deserialize`.
163///
164/// # Node Output
165///
166/// Node returns a [`flow_value::Map`][Map] as its output.
167///
168/// Building the output directly with [`flow_value::map!`][macro@map] and
169/// [`flow_value::array!`][macro@array] macros:
170/// ```
171/// let value = flow_value::map! {
172///     "customer_name" => "John",
173///     "items" => flow_value::array![1, 2, 3],
174/// };
175/// ```
176///
177/// [`Value`] also implements [`Serializer`][serde::Serializer], you can use
178/// [`flow_value::to_map`][to_map] to convert any type `T: Serialize` into [`value::Map`][Map].
179///
180/// ```
181/// #[derive(serde::Serialize)]
182/// struct Order {
183///     customer_name: String,
184///     items: Vec<i32>,
185/// }
186///
187/// flow_value::to_map(&Order {
188///     customer_name: "John".to_owned(),
189///     items: [1, 2, 3].into(),
190/// })
191/// .unwrap();
192/// ```
193///
194/// # JSON representation
195///
196/// When using [`Value`] in database and HTTP APIs, it is converted to a JSON object:
197///
198/// ```json
199/// {
200///     "<variant identifier>": <data>
201/// }
202/// ```
203///
204/// Identifiers of each enum variant:
205/// - **N**: [`Value::Null`]
206/// - **S**: [`Value::String`]
207/// - **B**: [`Value::Bool`]
208/// - **U**: [`Value::U64`]
209/// - **I**: [`Value::I64`]
210/// - **F**: [`Value::F64`]
211/// - **D**: [`Value::Decimal`]
212/// - **U1**: [`Value::U128`]
213/// - **I1**: [`Value::I128`]
214/// - **B3**: [`Value::B32`]
215/// - **B6**: [`Value::B64`]
216/// - **BY**: [`Value::Bytes`]
217/// - **A**: [`Value::Array`]
218/// - **M**: [`Value::Map`]
219///
220/// See variant's documentation to see how data are encoded.
221///
222/// Use [`serde_json`] to encode and decode [`Value`] as JSON:
223/// ```
224/// use flow_value::Value;
225///
226/// let value = Value::U64(10);
227///
228/// // encode Value to JSON
229/// let json = serde_json::to_string(&value).unwrap();
230/// assert_eq!(json, r#"{"U":"10"}"#);
231///
232/// // decode JSON to Value
233/// let value1 = serde_json::from_str::<Value>(&json).unwrap();
234/// assert_eq!(value1, value);
235/// ```
236#[derive(Clone, PartialEq, Default)]
237// #[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
238pub enum Value {
239    /// JSON representation:
240    /// ```json
241    /// { "N": 0 }
242    /// ```
243    #[default]
244    Null,
245    /// UTF-8 string.
246    ///
247    /// JSON representation:
248    /// ```json
249    /// { "S": "hello" }
250    /// ```
251    String(String),
252    /// JSON representation:
253    /// ```json
254    /// { "B": true }
255    /// ```
256    Bool(bool),
257    /// JSON representation:
258    /// ```json
259    /// { "U": "100" }
260    /// ```
261    ///
262    /// Numbers are encoded as JSON string to avoid losing precision when reading them in
263    /// Javascript/Typescript.
264    U64(u64),
265    /// JSON representation:
266    /// ```json
267    /// { "I": "-100" }
268    /// ```
269    I64(i64),
270    /// JSON representation:
271    /// ```json
272    /// { "F": "0.0" }
273    /// ```
274    /// Scientific notation is supported:
275    /// ```json
276    /// { "F": "1e9" }
277    /// ```
278    F64(f64),
279    /// [`rust_decimal::Decimal`], suitable for financial calculations.
280    ///
281    /// JSON representation:
282    /// ```json
283    /// { "D": "3.1415926535897932384626433832" }
284    /// ```
285    Decimal(Decimal),
286    /// JSON representation:
287    /// ```json
288    /// { "U1": "340282366920938463463374607431768211455" }
289    /// ```
290    U128(u128),
291    /// JSON representation:
292    /// ```json
293    /// { "I1": "-170141183460469231731687303715884105728" }
294    /// ```
295    I128(i128),
296    /// 32-bytes binary values, usually a Solana public key.
297    ///
298    /// JSON representation: encoded as a base-58 string
299    /// ```json
300    /// { "B3": "FMQUifdAHTytSxhiK4N7LmpvKRZaUmBnNnZmzFsdTPHB" }
301    /// ```
302    B32([u8; 32]),
303    /// 64-bytes binary values, usually a Solana signature or keypair.
304    ///
305    /// JSON representation: encoded as a base-58 string
306    /// ```json
307    /// { "B6": "4onDpbfeT7nNN9MNMvTEZRn6pbtrQc1pdTBJB4a7HbfhAE6c5bkbuuFfYtkqs99hAqp5o6j7W1VyuKDxCn79k3Tk" }
308    /// ```
309    B64([u8; 64]),
310    /// Binary values with length other than 32 and 64.
311    ///
312    /// JSON representation: encoded as a base-64 string
313    /// ```json
314    /// { "BY": "UmFpbnk=" }
315    /// ```
316    Bytes(bytes::Bytes),
317    /// An array of [`Value`]. Array can contains other arrays, maps, ect. Array elements do not
318    /// have to be of the same type.
319    ///
320    /// JSON representation:
321    ///
322    /// Example array containing a number and a string:
323    /// ```json
324    /// {
325    ///     "A": [
326    ///         { "U": 0 },
327    ///         { "S": "hello" }
328    ///     ]
329    /// }
330    /// ```
331    Array(Vec<Self>),
332    /// A key-value map, implemented with [`indexmap::IndexMap`], will preserve insertion order.
333    /// Keys are strings and values can be any [`Value`].
334    ///
335    /// JSON representation:
336    /// ```json
337    /// {
338    ///     "M": {
339    ///         "first name": { "S": "John" },
340    ///         "age": { "U": "20" }
341    ///     }
342    /// }
343    /// ```
344    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                            // unlikely to happen
443                            // if happen, probably a bug in serde_json
444                            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
736// default implementation of [u8] doesn't call serialize_bytes
737pub 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}