dynamodb_expression/value/num.rs
1use core::fmt::{self, LowerExp, UpperExp};
2
3use aws_sdk_dynamodb::types::AttributeValue;
4
5/// Represents a DynamoDB [numeric value][1].
6///
7/// See also:
8/// * [`Scalar::new_num`]
9/// * [`Value::new_num`]
10/// * [`Scalar::new_num_lower_exp`]
11/// * [`Value::new_num_lower_exp`]
12/// * [`Scalar::new_num_upper_exp`]
13/// * [`Value::new_num_upper_exp`]
14///
15/// # Examples
16///
17/// ```
18/// use dynamodb_expression::value::Num;
19/// # use pretty_assertions::assert_eq;
20///
21/// let value = Num::new(2600);
22/// assert_eq!("2600", value.to_string());
23///
24/// let value = Num::new_lower_exp(2600);
25/// assert_eq!("2.6e3", value.to_string());
26///
27/// let value = Num::new_upper_exp(2600);
28/// assert_eq!("2.6E3", value.to_string());
29///
30/// let value = Num::new(2600.0);
31/// assert_eq!("2600", value.to_string());
32///
33/// let value = Num::new_lower_exp(2600.0);
34/// assert_eq!("2.6e3", value.to_string());
35///
36/// let value = Num::new_upper_exp(2600.0);
37/// assert_eq!("2.6E3", value.to_string());
38/// ```
39///
40/// [1]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.Number
41/// [`Scalar::new_num`]: crate::value::Scalar::new_num
42/// [`Scalar::new_num_lower_exp`]: crate::value::Scalar::new_num_lower_exp
43/// [`Scalar::new_num_upper_exp`]: crate::value::Scalar::new_num_upper_exp
44/// [`Value::new_num`]: crate::value::Value::new_num
45/// [`Value::new_num_lower_exp`]: crate::value::Value::new_num_lower_exp
46/// [`Value::new_num_upper_exp`]: crate::value::Value::new_num_upper_exp
47#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
48pub struct Num {
49 pub(crate) n: String,
50}
51
52impl Num {
53 /// Creates a DynamoDB [numeric value][1].
54 ///
55 /// See also: [`Num::new_lower_exp`], [`Num::new_upper_exp`], [`Scalar::new_num`],
56 /// [`Value::new_num`]
57 ///
58 /// # Examples
59 ///
60 /// ```
61 /// use dynamodb_expression::value::Num;
62 /// # use pretty_assertions::assert_eq;
63 ///
64 /// let value = Num::new(2600);
65 /// assert_eq!("2600", value.to_string());
66 ///
67 /// let value = Num::new(2600.0);
68 /// assert_eq!("2600", value.to_string());
69 /// ```
70 ///
71 /// [1]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.Number
72 /// [`Scalar::new_num`]: crate::value::Scalar::new_num
73 /// [`Value::new_num`]: crate::value::Value::new_num
74 pub fn new<T>(value: T) -> Self
75 where
76 T: ToString + num::Num,
77 {
78 Self {
79 n: value.to_string(),
80 }
81 }
82
83 /// Creates a DynamoDB [numeric value][1].
84 ///
85 /// See also: [`Num::new`], [`Num::new_upper_exp`], [`Scalar::new_num_lower_exp`],
86 /// [`Value::new_num_lower_exp`]
87 ///
88 /// # Examples
89 ///
90 /// ```
91 /// use dynamodb_expression::value::Num;
92 /// # use pretty_assertions::assert_eq;
93 ///
94 /// let value = Num::new_lower_exp(2600);
95 /// assert_eq!("2.6e3", value.to_string());
96 ///
97 /// let value = Num::new_lower_exp(2600.0);
98 /// assert_eq!("2.6e3", value.to_string());
99 /// ```
100 ///
101 /// [1]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.Number
102 /// [`Scalar::new_num_lower_exp`]: crate::value::Scalar::new_num_lower_exp
103 /// [`Value::new_num_lower_exp`]: crate::value::Value::new_num_lower_exp
104 pub fn new_lower_exp<T>(value: T) -> Self
105 where
106 T: LowerExp + num::Num,
107 {
108 Self {
109 n: format!("{value:e}"),
110 }
111 }
112
113 /// Creates a DynamoDB [numeric value][1].
114 ///
115 /// See also: [`Num::new`], [`Num::new_lower_exp`], [`Scalar::new_num_upper_exp`],
116 /// [`Value::new_num_upper_exp`]
117 ///
118 /// # Examples
119 ///
120 /// ```
121 /// use dynamodb_expression::value::Num;
122 /// # use pretty_assertions::assert_eq;
123 ///
124 /// let value = Num::new_upper_exp(2600);
125 /// assert_eq!("2.6E3", value.to_string());
126 ///
127 /// let value = Num::new_upper_exp(2600.0);
128 /// assert_eq!("2.6E3", value.to_string());
129 /// ```
130 ///
131 /// [1]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.Number
132 /// [`Scalar::new_num_upper_exp`]: crate::value::Scalar::new_num_upper_exp
133 /// [`Value::new_num_upper_exp`]: crate::value::Value::new_num_upper_exp
134 pub fn new_upper_exp<T>(value: T) -> Self
135 where
136 T: UpperExp + num::Num,
137 {
138 Self {
139 n: format!("{value:E}"),
140 }
141 }
142
143 // Intentionally not using `impl From<Num> for AttributeValue` because
144 // I don't want to make this a public API people rely on. The purpose of this
145 // crate is not to make creating `AttributeValues` easier. They should try
146 // `serde_dynamo`.
147 pub(super) fn into_attribute_value(self) -> AttributeValue {
148 AttributeValue::N(self.n)
149 }
150}
151
152impl fmt::Display for Num {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 self.n.fmt(f)
155 }
156}
157
158impl<T> From<T> for Num
159where
160 T: ToString + num::Num,
161{
162 fn from(num: T) -> Self {
163 Num::new(num)
164 }
165}
166
167impl From<Num> for String {
168 fn from(num: Num) -> Self {
169 num.n
170 }
171}