taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

de.rs (7176B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 
     17 use serde::{
     18     Deserialize,
     19     de::{self, Error, Visitor, value::SeqDeserializer},
     20     forward_to_deserialize_any,
     21 };
     22 
     23 /// Parse notification message content
     24 pub fn from_str<'de, T: Deserialize<'de>>(
     25     notification: &'de str,
     26 ) -> Result<T, serde::de::value::Error> {
     27     T::deserialize(Deserializer(notification))
     28 }
     29 
     30 macro_rules! gen_fn {
     31     (deserialize_unit_struct, $self:ident, $v:ident, $content:block) => {
     32         gen_fn!(deserialize_unit_struct, $self, (_name: &'static str, $v: V), $content);
     33     };
     34     (deserialize_newtype_struct, $self:ident, $v:ident, $content:block) => {
     35         gen_fn!(deserialize_newtype_struct, $self, (_name: &'static str, $v: V), $content);
     36     };
     37     (deserialize_tuple, $self:ident, $v:ident, $content:block) => {
     38         gen_fn!(deserialize_tuple, $self, (_len: usize, $v: V), $content);
     39     };
     40     (deserialize_tuple_struct, $self:ident, $v:ident, $content:block) => {
     41         gen_fn!(deserialize_tuple_struct, $self, (_name: &'static str, _len: usize, $v: V), $content);
     42     };
     43     (deserialize_struct, $self:ident, $v:ident, $content:block) => {
     44         gen_fn!(deserialize_struct, $self, (_name: &'static str, _fields: &'static [&'static str], $v: V), $content);
     45     };
     46     (deserialize_enum, $self:ident, $v:ident, $content:block) => {
     47         gen_fn!(deserialize_enum, $self, (_name: &'static str, _variants: &'static [&'static str], $v: V), $content);
     48     };
     49     ($fn:ident, $self:ident, $v:ident, $content:block) => { gen_fn!($fn, $self, ($v: V), $content); };
     50     ($fn:ident, $self:ident, ($($arg:ident: $type:ty),*), $content:block) => {
     51         fn $fn<V: Visitor<'de>>($self$(, $arg: $type)*) -> Result<V::Value, de::value::Error> {
     52             $content
     53         }
     54     };
     55 }
     56 
     57 macro_rules! forward_to_parse {
     58     ($(($from:ident, $visit_func:ident)),*$(,)?) => {
     59         $(
     60             gen_fn!($from, self, visitor, {
     61                 visitor.$visit_func(
     62                     self.0
     63                         .parse()
     64                         .map_err(|e| Error::custom(format!("{}", e)))?,
     65                 )
     66             });
     67         )*
     68     }
     69 }
     70 
     71 macro_rules! forward_to_other {
     72     ($(($from:ident, $to:ident)),*$(,)?) => {
     73         $(
     74             gen_fn!($from, self, visitor, {
     75                 self.$to(visitor)
     76             });
     77         )*
     78     }
     79 }
     80 
     81 macro_rules! fail_unsupported {
     82     ($(($from:ident, $ty:expr)),*$(,)?) => {
     83         $(
     84             gen_fn!($from, self, _visitor, {
     85                 Err(Error::custom(format!("cannot deserialize non primitive type {}", $ty)))
     86             });
     87         )*
     88     }
     89 }
     90 
     91 /// Space-separated values deserializer for Postgres notification
     92 /// Support tuples only
     93 struct Deserializer<'de>(&'de str);
     94 
     95 impl<'de> serde::de::Deserializer<'de> for Deserializer<'de> {
     96     type Error = de::value::Error;
     97 
     98     fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
     99     where
    100         V: Visitor<'de>,
    101     {
    102         let de = SeqDeserializer::new(self.0.split(' ').map(PlainDe));
    103         visitor.visit_seq(de)
    104     }
    105 
    106     fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    107     where
    108         V: Visitor<'de>,
    109     {
    110         PlainDe(self.0).deserialize_unit(visitor)
    111     }
    112 
    113     forward_to_deserialize_any! {
    114         bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
    115         bytes byte_buf option unit_struct newtype_struct seq tuple
    116         tuple_struct map struct enum identifier ignored_any
    117     }
    118 }
    119 
    120 /// Deserializer for any plain value that can be parsed from a string
    121 struct PlainDe<'de>(&'de str);
    122 
    123 impl<'de> serde::de::IntoDeserializer<'de> for PlainDe<'de> {
    124     type Deserializer = Self;
    125 
    126     fn into_deserializer(self) -> Self::Deserializer {
    127         self
    128     }
    129 }
    130 
    131 impl<'de> serde::de::Deserializer<'de> for PlainDe<'de> {
    132     type Error = serde::de::value::Error;
    133 
    134     fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    135     where
    136         V: Visitor<'de>,
    137     {
    138         visitor.visit_borrowed_str(self.0)
    139     }
    140 
    141     fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    142     where
    143         V: Visitor<'de>,
    144     {
    145         if self.0.is_empty() {
    146             visitor.visit_none()
    147         } else {
    148             visitor.visit_some(self)
    149         }
    150     }
    151 
    152     fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    153     where
    154         V: Visitor<'de>,
    155     {
    156         if self.0.is_empty() {
    157             visitor.visit_unit()
    158         } else {
    159             Err(Error::custom("expected empty string for unit"))
    160         }
    161     }
    162 
    163     forward_to_parse!(
    164         (deserialize_i8, visit_i8),
    165         (deserialize_i16, visit_i16),
    166         (deserialize_i32, visit_i32),
    167         (deserialize_i64, visit_i64),
    168         (deserialize_i128, visit_i128),
    169         (deserialize_u8, visit_u8),
    170         (deserialize_u16, visit_u16),
    171         (deserialize_u32, visit_u32),
    172         (deserialize_u64, visit_u64),
    173         (deserialize_u128, visit_u128),
    174         (deserialize_f32, visit_f32),
    175         (deserialize_f64, visit_f64),
    176         (deserialize_char, visit_char),
    177         (deserialize_bool, visit_bool)
    178     );
    179 
    180     forward_to_other!(
    181         (deserialize_string, deserialize_str),
    182         (deserialize_any, deserialize_str),
    183         (deserialize_unit_struct, deserialize_unit),
    184     );
    185 
    186     fail_unsupported!(
    187         (deserialize_bytes, "bytes"),
    188         (deserialize_byte_buf, "bytes"),
    189         (deserialize_seq, "seq"),
    190         (deserialize_tuple_struct, "tuple"),
    191         (deserialize_tuple, "tuple"),
    192         (deserialize_map, "map"),
    193         (deserialize_struct, "struct"),
    194         (deserialize_newtype_struct, "struct"),
    195         (deserialize_enum, "enum"),
    196         (deserialize_identifier, "identifier"),
    197         (deserialize_ignored_any, "any")
    198     );
    199 }
    200 
    201 #[test]
    202 pub fn parse() {
    203     // Parse simple message
    204     assert_eq!((1,), from_str::<(u8,)>("1").unwrap());
    205     assert_eq!((false,), from_str::<(bool,)>("false").unwrap());
    206     assert_eq!(("username",), from_str::<(&str,)>("username").unwrap());
    207 
    208     // Parse composite message
    209     assert_eq!((1, false), from_str::<(u8, bool)>("1 false").unwrap());
    210     assert_eq!([1, 2, 3, 4], from_str::<[u8; 4]>("1 2 3 4").unwrap());
    211 
    212     // Parse corner case
    213     assert_eq!((), from_str::<()>("").unwrap());
    214     assert_eq!((1, None), from_str::<(u8, Option<bool>)>("1 ").unwrap());
    215     assert_eq!((1, ()), from_str::<(u8, ())>("1 ").unwrap());
    216     assert_eq!(
    217         (1, (), true),
    218         from_str::<(u8, (), bool)>("1  true").unwrap()
    219     );
    220 }