taler-rust

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

api_params.rs (3847B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2024, 2025, 2026 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::Deserialize;
     18 use serde_with::{DisplayFromStr, serde_as};
     19 
     20 use crate::{api_wire::TransferState, types::payto::PaytoURI};
     21 
     22 #[derive(Debug, thiserror::Error)]
     23 #[error("Param '{param}' {reason}")]
     24 pub struct ParamsErr {
     25     pub param: &'static str,
     26     pub reason: String,
     27 }
     28 
     29 pub fn param_err(param: &'static str, reason: String) -> ParamsErr {
     30     ParamsErr { param, reason }
     31 }
     32 
     33 #[serde_as]
     34 #[derive(Debug, Clone, Deserialize)]
     35 /// <https://docs.taler.net/core/api-common.html#row-id-pagination>
     36 pub struct PageParams {
     37     #[serde_as(as = "Option<DisplayFromStr>")]
     38     #[serde(alias = "delta")]
     39     pub limit: Option<i64>,
     40     #[serde_as(as = "Option<DisplayFromStr>")]
     41     #[serde(alias = "start")]
     42     pub offset: Option<i64>,
     43 }
     44 
     45 impl PageParams {
     46     const MAX_PAGE_SIZE: i64 = 1024;
     47 
     48     pub fn check(self) -> Result<Page, ParamsErr> {
     49         Self::check_custom(self, Self::MAX_PAGE_SIZE)
     50     }
     51 
     52     pub fn check_custom(self, max_page_size: i64) -> Result<Page, ParamsErr> {
     53         let limit = self.limit.unwrap_or(-20);
     54         if limit == 0 {
     55             return Err(param_err("limit", format!("must be non-zero got {limit}")));
     56         } else if limit > max_page_size {
     57             return Err(param_err(
     58                 "limit",
     59                 format!("must be <= {max_page_size} for {limit}"),
     60             ));
     61         }
     62         if let Some(offset) = self.offset
     63             && offset < 0
     64         {
     65             return Err(param_err(
     66                 "offset",
     67                 format!("must be positive got {offset}"),
     68             ));
     69         }
     70 
     71         Ok(Page {
     72             limit,
     73             offset: self.offset,
     74         })
     75     }
     76 }
     77 
     78 #[derive(Debug)]
     79 pub struct Page {
     80     pub limit: i64,
     81     pub offset: Option<i64>,
     82 }
     83 
     84 impl Default for Page {
     85     fn default() -> Self {
     86         Self {
     87             limit: 20,
     88             offset: None,
     89         }
     90     }
     91 }
     92 
     93 impl Page {
     94     pub fn backward(&self) -> bool {
     95         self.limit < 0
     96     }
     97 }
     98 
     99 #[derive(Debug, Clone, Deserialize)]
    100 /// <https://docs.taler.net/core/api-common.html#long-polling>
    101 pub struct HistoryParams {
    102     #[serde(flatten)]
    103     pub pagination: PageParams,
    104     #[serde(alias = "long_poll_ms")]
    105     pub timeout_ms: Option<u64>,
    106 }
    107 
    108 impl HistoryParams {
    109     pub const MAX_TIMEOUT_MS: u64 = 60 * 60 * 10; // 1H
    110 
    111     pub fn check(self) -> Result<History, ParamsErr> {
    112         Self::check_custom(self, PageParams::MAX_PAGE_SIZE, Self::MAX_TIMEOUT_MS)
    113     }
    114 
    115     pub fn check_custom(
    116         self,
    117         max_page_size: i64,
    118         max_timeout_ms: u64,
    119     ) -> Result<History, ParamsErr> {
    120         let timeout_ms = self.timeout_ms.map(|it| it.min(max_timeout_ms));
    121         Ok(History {
    122             page: self.pagination.check_custom(max_page_size)?,
    123             timeout_ms,
    124         })
    125     }
    126 }
    127 
    128 #[derive(Debug, Default)]
    129 pub struct History {
    130     pub page: Page,
    131     pub timeout_ms: Option<u64>,
    132 }
    133 
    134 #[derive(Debug, Clone, Deserialize)]
    135 pub struct TransferParams {
    136     #[serde(flatten)]
    137     pub pagination: PageParams,
    138     pub status: Option<TransferState>,
    139 }
    140 
    141 #[derive(Debug, Clone, Deserialize)]
    142 pub struct AccountParams {
    143     pub account: PaytoURI,
    144 }