tiberius/tds/codec/column_data/
money.rs

1use crate::{error::Error, numeric::Numeric, sql_read_bytes::SqlReadBytes, ColumnData};
2
3/// Decode 'money' and 'smallmoney' types according to the TDS spec.
4///
5/// See: <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/1266679d-cd6e-492a-b2b2-3a9ba004196d>.
6pub(crate) async fn decode<R>(src: &mut R, len: u8) -> crate::Result<ColumnData<'static>>
7where
8    R: SqlReadBytes + Unpin,
9{
10    /// According to the TDS spec both money types are sent over the wire with
11    /// a scale of 4 (aka ten-thousandth).
12    const SCALE: u8 = 4;
13
14    let res = match len {
15        0 => ColumnData::Numeric(None),
16        4 => {
17            let value = src.read_i32_le().await?;
18            let value = Numeric::new_with_scale(value.into(), SCALE);
19            ColumnData::Numeric(Some(value))
20        }
21        8 => {
22            let high = src.read_i32_le().await?;
23            let low = src.read_u32_le().await?;
24
25            let value = (high as i64) << 32 | (low as i64);
26            let value = Numeric::new_with_scale(value.into(), SCALE);
27            ColumnData::Numeric(Some(value))
28        }
29        _ => {
30            return Err(Error::Protocol(
31                format!("money: length of {} is invalid", len).into(),
32            ))
33        }
34    };
35
36    Ok(res)
37}