api_common.rs (3679B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 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 std::{fmt::Display, ops::Deref}; 18 19 use rand_core::OsRng; 20 use serde::{Deserialize, Deserializer, Serialize, de::Error}; 21 use serde_json::value::RawValue; 22 23 use crate::types::base32::Base32; 24 25 /// <https://docs.taler.net/core/api-common.html#tsref-type-ErrorDetail> 26 #[derive(Debug, Clone, Serialize, Deserialize)] 27 pub struct ErrorDetail { 28 pub code: u32, 29 pub hint: Option<Box<str>>, 30 pub detail: Option<Box<str>>, 31 pub parameter: Option<Box<str>>, 32 pub path: Option<Box<str>>, 33 pub offset: Option<Box<str>>, 34 pub index: Option<Box<str>>, 35 pub object: Option<Box<str>>, 36 pub currency: Option<Box<str>>, 37 pub type_expected: Option<Box<str>>, 38 pub type_actual: Option<Box<str>>, 39 pub extra: Option<Box<RawValue>>, 40 } 41 42 pub fn safe_u64(nb: u64) -> SafeU64 { 43 SafeU64::try_from(nb).expect("invalid safe u64") 44 } 45 46 /// <https://docs.taler.net/core/api-common.html#tsref-type-SafeUint64> 47 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize)] 48 pub struct SafeU64(u64); 49 50 impl Deref for SafeU64 { 51 type Target = u64; 52 53 fn deref(&self) -> &Self::Target { 54 &self.0 55 } 56 } 57 58 #[derive(Debug, thiserror::Error)] 59 pub enum SafeU64Error { 60 #[error("{0} unsafe, {0} > (2^53 - 1)")] 61 Unsafe(u64), 62 #[error("{0} is negative")] 63 Negative(i64), 64 } 65 66 impl TryFrom<u64> for SafeU64 { 67 type Error = SafeU64Error; 68 69 fn try_from(nb: u64) -> Result<Self, Self::Error> { 70 if nb < (1 << 53) - 1 { 71 Ok(SafeU64(nb)) 72 } else { 73 Err(SafeU64Error::Unsafe(nb)) 74 } 75 } 76 } 77 78 impl TryFrom<i64> for SafeU64 { 79 type Error = SafeU64Error; 80 81 fn try_from(nb: i64) -> Result<Self, Self::Error> { 82 u64::try_from(nb) 83 .map_err(|_| SafeU64Error::Negative(nb)) 84 .and_then(|it| it.try_into()) 85 } 86 } 87 88 impl TryFrom<i32> for SafeU64 { 89 type Error = SafeU64Error; 90 91 fn try_from(nb: i32) -> Result<Self, Self::Error> { 92 u64::try_from(nb) 93 .map_err(|_| SafeU64Error::Negative(nb as i64)) 94 .and_then(|it| it.try_into()) 95 } 96 } 97 98 impl<'de> Deserialize<'de> for SafeU64 { 99 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 100 where 101 D: Deserializer<'de>, 102 { 103 SafeU64::try_from(u64::deserialize(deserializer)?).map_err(D::Error::custom) 104 } 105 } 106 107 impl Display for SafeU64 { 108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 109 self.0.fmt(f) 110 } 111 } 112 113 /// EdDSA and ECDHE public keys always point on Curve25519 114 /// and represented using the standard 256 bits Ed25519 compact format, 115 /// converted to Crockford Base32. 116 pub type EddsaPublicKey = Base32<32>; 117 /// 64-byte hash code 118 pub type HashCode = Base32<64>; 119 /// 32-bytes hash code 120 pub type ShortHashCode = Base32<32>; 121 pub type WadId = Base32<24>; 122 123 pub fn rand_edsa_pub_key() -> EddsaPublicKey { 124 let signing_key = ed25519_dalek::SigningKey::generate(&mut OsRng); 125 Base32::from(signing_key.verifying_key().to_bytes()) 126 }