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