sqlx_exasol/types/
uint.rs

1use serde::Deserialize;
2use serde_json::Value;
3use sqlx_core::{
4    decode::Decode,
5    encode::{Encode, IsNull},
6    error::BoxDynError,
7    types::Type,
8};
9
10use crate::{
11    arguments::ExaBuffer,
12    database::Exasol,
13    type_info::{Decimal, ExaDataType, ExaTypeInfo},
14    value::ExaValueRef,
15};
16
17/// Numbers below this threshold must be serialized/deserialized as integers.
18/// The ones above must be treated as strings.
19const MAX_U64_NUMERIC: u64 = 1_000_000_000_000_000_000;
20const MAX_U128_NUMERIC: u128 = 1_000_000_000_000_000_000;
21
22impl Type<Exasol> for u8 {
23    fn type_info() -> ExaTypeInfo {
24        ExaDataType::Decimal(Decimal::new(Decimal::MAX_8BIT_PRECISION, 0)).into()
25    }
26
27    fn compatible(ty: &ExaTypeInfo) -> bool {
28        <Self as Type<Exasol>>::type_info().compatible(ty)
29    }
30}
31
32impl Encode<'_, Exasol> for u8 {
33    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
34        buf.append(self)?;
35        Ok(IsNull::No)
36    }
37
38    fn produces(&self) -> Option<ExaTypeInfo> {
39        let precision = self.checked_ilog10().unwrap_or_default() + 1;
40        Some(ExaDataType::Decimal(Decimal::new(precision, 0)).into())
41    }
42
43    fn size_hint(&self) -> usize {
44        Decimal::MAX_8BIT_PRECISION as usize
45    }
46}
47
48impl Decode<'_, Exasol> for u8 {
49    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
50        <Self as Deserialize>::deserialize(value.value).map_err(From::from)
51    }
52}
53
54impl Type<Exasol> for u16 {
55    fn type_info() -> ExaTypeInfo {
56        ExaDataType::Decimal(Decimal::new(Decimal::MAX_16BIT_PRECISION, 0)).into()
57    }
58
59    fn compatible(ty: &ExaTypeInfo) -> bool {
60        <Self as Type<Exasol>>::type_info().compatible(ty)
61    }
62}
63
64impl Encode<'_, Exasol> for u16 {
65    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
66        buf.append(self)?;
67        Ok(IsNull::No)
68    }
69
70    fn produces(&self) -> Option<ExaTypeInfo> {
71        let precision = self.checked_ilog10().unwrap_or_default() + 1;
72        Some(ExaDataType::Decimal(Decimal::new(precision, 0)).into())
73    }
74
75    fn size_hint(&self) -> usize {
76        Decimal::MAX_16BIT_PRECISION as usize
77    }
78}
79
80impl Decode<'_, Exasol> for u16 {
81    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
82        <Self as Deserialize>::deserialize(value.value).map_err(From::from)
83    }
84}
85
86impl Type<Exasol> for u32 {
87    fn type_info() -> ExaTypeInfo {
88        ExaDataType::Decimal(Decimal::new(Decimal::MAX_32BIT_PRECISION, 0)).into()
89    }
90
91    fn compatible(ty: &ExaTypeInfo) -> bool {
92        <Self as Type<Exasol>>::type_info().compatible(ty)
93    }
94}
95
96impl Encode<'_, Exasol> for u32 {
97    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
98        buf.append(self)?;
99        Ok(IsNull::No)
100    }
101
102    fn produces(&self) -> Option<ExaTypeInfo> {
103        let precision = self.checked_ilog10().unwrap_or_default() + 1;
104        Some(ExaDataType::Decimal(Decimal::new(precision, 0)).into())
105    }
106
107    fn size_hint(&self) -> usize {
108        Decimal::MAX_32BIT_PRECISION as usize
109    }
110}
111
112impl Decode<'_, Exasol> for u32 {
113    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
114        <Self as Deserialize>::deserialize(value.value).map_err(From::from)
115    }
116}
117
118impl Type<Exasol> for u64 {
119    fn type_info() -> ExaTypeInfo {
120        ExaDataType::Decimal(Decimal::new(Decimal::MAX_64BIT_PRECISION, 0)).into()
121    }
122
123    fn compatible(ty: &ExaTypeInfo) -> bool {
124        <Self as Type<Exasol>>::type_info().compatible(ty)
125    }
126}
127
128impl Encode<'_, Exasol> for u64 {
129    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
130        if self < &MAX_U64_NUMERIC {
131            buf.append(self)?;
132        } else {
133            // Large numbers get serialized as strings
134            buf.append(format_args!("{self}"))?;
135        };
136
137        Ok(IsNull::No)
138    }
139
140    fn produces(&self) -> Option<ExaTypeInfo> {
141        let precision = self.checked_ilog10().unwrap_or_default() + 1;
142        Some(ExaDataType::Decimal(Decimal::new(precision, 0)).into())
143    }
144
145    fn size_hint(&self) -> usize {
146        Decimal::MAX_64BIT_PRECISION as usize
147    }
148}
149
150impl Decode<'_, Exasol> for u64 {
151    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
152        match value.value {
153            Value::Number(n) => <Self as Deserialize>::deserialize(n).map_err(From::from),
154            Value::String(s) => serde_json::from_str(s).map_err(From::from),
155            v => Err(format!("invalid u64 value: {v}").into()),
156        }
157    }
158}
159
160impl Type<Exasol> for u128 {
161    fn type_info() -> ExaTypeInfo {
162        ExaDataType::Decimal(Decimal::new(Decimal::MAX_128BIT_PRECISION, 0)).into()
163    }
164
165    fn compatible(ty: &ExaTypeInfo) -> bool {
166        <Self as Type<Exasol>>::type_info().compatible(ty)
167    }
168}
169
170impl Encode<'_, Exasol> for u128 {
171    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
172        if self < &MAX_U128_NUMERIC {
173            buf.append(self)?;
174        } else {
175            // Large numbers get serialized as strings
176            buf.append(format_args!("{self}"))?;
177        };
178
179        Ok(IsNull::No)
180    }
181
182    fn produces(&self) -> Option<ExaTypeInfo> {
183        let precision = self.checked_ilog10().unwrap_or_default() + 1;
184        Some(ExaDataType::Decimal(Decimal::new(precision, 0)).into())
185    }
186
187    fn size_hint(&self) -> usize {
188        Decimal::MAX_128BIT_PRECISION as usize
189    }
190}
191
192impl Decode<'_, Exasol> for u128 {
193    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
194        match value.value {
195            Value::Number(n) => <Self as Deserialize>::deserialize(n).map_err(From::from),
196            Value::String(s) => serde_json::from_str(s).map_err(From::from),
197            v => Err(format!("invalid u128 value: {v}").into()),
198        }
199    }
200}