strings not used internally11
This commit is contained in:
@@ -8,6 +8,49 @@
|
||||
//! would reject, and each side renders the shared error as its own error type.
|
||||
|
||||
pub use rusty_money::iso;
|
||||
pub use crate::proto::komp_ac::table_definition::MoneyRounding;
|
||||
|
||||
impl MoneyRounding {
|
||||
pub fn as_storage_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::None => "none",
|
||||
Self::HalfUp => "half_up",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for MoneyRounding {
|
||||
type Err = serde::de::value::Error;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"none" => Ok(Self::None),
|
||||
"half_up" => Ok(Self::HalfUp),
|
||||
_ => Err(serde::de::Error::custom(format!("Invalid money rounding: {value}"))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for MoneyRounding {
|
||||
type Error = serde::de::value::Error;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
value.parse()
|
||||
}
|
||||
}
|
||||
|
||||
pub mod rounding_serde {
|
||||
use super::MoneyRounding;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S: Serializer>(value: &MoneyRounding, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_str(value.as_storage_str())
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<MoneyRounding, D::Error> {
|
||||
String::deserialize(deserializer)?.parse().map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves a canonical uppercase ISO-4217 alphabetic code to its currency.
|
||||
///
|
||||
@@ -40,6 +83,34 @@ pub fn iso_currency_codes() -> Vec<&'static str> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn rounding_storage_and_json_boundaries_are_strict() {
|
||||
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
struct StoredPolicy {
|
||||
#[serde(with = "super::rounding_serde")]
|
||||
rounding: MoneyRounding,
|
||||
}
|
||||
|
||||
for (text, policy) in [("none", MoneyRounding::None), ("half_up", MoneyRounding::HalfUp)] {
|
||||
assert_eq!(text.parse::<MoneyRounding>().unwrap(), policy);
|
||||
assert_eq!(MoneyRounding::try_from(text.to_string()).unwrap(), policy);
|
||||
assert_eq!(policy.as_storage_str(), text);
|
||||
let stored = StoredPolicy { rounding: policy };
|
||||
let json = serde_json::json!({ "rounding": text });
|
||||
assert_eq!(serde_json::to_value(&stored).unwrap(), json);
|
||||
assert_eq!(serde_json::from_value::<StoredPolicy>(json).unwrap(), stored);
|
||||
}
|
||||
for text in ["", "NONE", "HalfUp", "half-up", " half_up", "half_up ", "unknown"] {
|
||||
assert!(text.parse::<MoneyRounding>().is_err());
|
||||
assert!(serde_json::from_value::<StoredPolicy>(serde_json::json!({ "rounding": text })).is_err());
|
||||
}
|
||||
for value in [serde_json::Value::Null, serde_json::json!(0), serde_json::json!(1)] {
|
||||
assert!(serde_json::from_value::<StoredPolicy>(serde_json::json!({ "rounding": value })).is_err());
|
||||
}
|
||||
assert!(MoneyRounding::try_from(-1).is_err());
|
||||
assert!(MoneyRounding::try_from(2).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canonical_codes_resolve_to_their_currency() {
|
||||
assert_eq!(require_iso_currency_code("EUR").unwrap(), iso::EUR);
|
||||
|
||||
Binary file not shown.
@@ -36,8 +36,8 @@ pub struct AnalyticsCatalogColumn {
|
||||
pub field_type: ::prost::alloc::string::String,
|
||||
#[prost(bool, tag = "3")]
|
||||
pub is_system: bool,
|
||||
#[prost(string, tag = "4")]
|
||||
pub rounding: ::prost::alloc::string::String,
|
||||
#[prost(enumeration = "super::table_definition::MoneyRounding", tag = "4")]
|
||||
pub rounding: i32,
|
||||
/// Canonical ISO-4217 code for MONEY; empty for every other type.
|
||||
#[prost(string, tag = "5")]
|
||||
pub currency: ::prost::alloc::string::String,
|
||||
|
||||
@@ -120,8 +120,8 @@ pub struct Document {
|
||||
pub source_records: ::prost::alloc::vec::Vec<SourceRecord>,
|
||||
#[prost(string, tag = "5")]
|
||||
pub data_json: ::prost::alloc::string::String,
|
||||
#[prost(string, tag = "6")]
|
||||
pub change_kind: ::prost::alloc::string::String,
|
||||
#[prost(enumeration = "DocumentDataChangeKind", tag = "6")]
|
||||
pub change_kind: i32,
|
||||
#[prost(int32, tag = "7")]
|
||||
pub version_number: i32,
|
||||
#[prost(string, tag = "8")]
|
||||
@@ -221,6 +221,36 @@ pub struct GetTypstTemplateVersionResponse {
|
||||
#[prost(message, optional, tag = "1")]
|
||||
pub template_version: ::core::option::Option<TypstTemplateVersion>,
|
||||
}
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum DocumentDataChangeKind {
|
||||
Unspecified = 0,
|
||||
Generated = 1,
|
||||
UserAdjustment = 2,
|
||||
}
|
||||
impl DocumentDataChangeKind {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Unspecified => "DOCUMENT_DATA_CHANGE_KIND_UNSPECIFIED",
|
||||
Self::Generated => "DOCUMENT_DATA_CHANGE_KIND_GENERATED",
|
||||
Self::UserAdjustment => "DOCUMENT_DATA_CHANGE_KIND_USER_ADJUSTMENT",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"DOCUMENT_DATA_CHANGE_KIND_UNSPECIFIED" => Some(Self::Unspecified),
|
||||
"DOCUMENT_DATA_CHANGE_KIND_GENERATED" => Some(Self::Generated),
|
||||
"DOCUMENT_DATA_CHANGE_KIND_USER_ADJUSTMENT" => Some(Self::UserAdjustment),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Generated client implementations.
|
||||
pub mod document_data_service_client {
|
||||
#![allow(
|
||||
|
||||
@@ -59,8 +59,8 @@ pub struct PreviewDirectConversionResponse {
|
||||
pub conversion_basis_date: ::prost::alloc::string::String,
|
||||
#[prost(string, tag = "6")]
|
||||
pub determination_method: ::prost::alloc::string::String,
|
||||
#[prost(string, tag = "7")]
|
||||
pub rounding_method: ::prost::alloc::string::String,
|
||||
#[prost(enumeration = "super::table_definition::MoneyRounding", tag = "7")]
|
||||
pub rounding_method: i32,
|
||||
#[prost(string, optional, tag = "8")]
|
||||
pub rate_date: ::core::option::Option<::prost::alloc::string::String>,
|
||||
#[prost(string, optional, tag = "9")]
|
||||
@@ -141,8 +141,8 @@ pub struct ConversionEvidence {
|
||||
pub conversion_basis_date: ::prost::alloc::string::String,
|
||||
#[prost(string, tag = "12")]
|
||||
pub determination_method: ::prost::alloc::string::String,
|
||||
#[prost(string, tag = "13")]
|
||||
pub rounding_method: ::prost::alloc::string::String,
|
||||
#[prost(enumeration = "super::table_definition::MoneyRounding", tag = "13")]
|
||||
pub rounding_method: i32,
|
||||
#[prost(string, optional, tag = "14")]
|
||||
pub rate_date: ::core::option::Option<::prost::alloc::string::String>,
|
||||
#[prost(string, tag = "15")]
|
||||
|
||||
Reference in New Issue
Block a user