Skip to main content

mz_expr/scalar/func/impls/
uint16.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use std::fmt;
11
12use mz_expr_derive::sqlfunc;
13use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale};
14use mz_repr::{SqlColumnType, SqlScalarType, strconv};
15use serde::{Deserialize, Serialize};
16
17use crate::EvalError;
18use crate::scalar::func::EagerUnaryFunc;
19
20#[sqlfunc(
21    sqlname = "~",
22    preserves_uniqueness = true,
23    inverse = to_unary!(super::BitNotUint16)
24)]
25fn bit_not_uint16(a: u16) -> u16 {
26    !a
27}
28
29#[sqlfunc(
30    sqlname = "uint2_to_real",
31    preserves_uniqueness = true,
32    inverse = to_unary!(super::CastFloat32ToUint16),
33    is_monotone = true
34)]
35fn cast_uint16_to_float32(a: u16) -> f32 {
36    f32::from(a)
37}
38
39#[sqlfunc(
40    sqlname = "uint2_to_double",
41    preserves_uniqueness = true,
42    inverse = to_unary!(super::CastFloat64ToUint16),
43    is_monotone = true
44)]
45fn cast_uint16_to_float64(a: u16) -> f64 {
46    f64::from(a)
47}
48
49#[sqlfunc(
50    sqlname = "uint2_to_uint4",
51    preserves_uniqueness = true,
52    inverse = to_unary!(super::CastUint32ToUint16),
53    is_monotone = true
54)]
55fn cast_uint16_to_uint32(a: u16) -> u32 {
56    u32::from(a)
57}
58
59#[sqlfunc(
60    sqlname = "uint2_to_uint8",
61    preserves_uniqueness = true,
62    inverse = to_unary!(super::CastUint64ToUint16),
63    is_monotone = true
64)]
65fn cast_uint16_to_uint64(a: u16) -> u64 {
66    u64::from(a)
67}
68
69#[sqlfunc(
70    sqlname = "uint2_to_smallint",
71    preserves_uniqueness = true,
72    inverse = to_unary!(super::CastInt16ToUint16),
73    is_monotone = true
74)]
75fn cast_uint16_to_int16(a: u16) -> Result<i16, EvalError> {
76    i16::try_from(a).or_else(|_| Err(EvalError::Int16OutOfRange(a.to_string().into())))
77}
78
79#[sqlfunc(
80    sqlname = "uint2_to_integer",
81    preserves_uniqueness = true,
82    inverse = to_unary!(super::CastInt32ToUint16),
83    is_monotone = true
84)]
85fn cast_uint16_to_int32(a: u16) -> i32 {
86    i32::from(a)
87}
88#[sqlfunc(
89    sqlname = "uint2_to_bigint",
90    preserves_uniqueness = true,
91    inverse = to_unary!(super::CastInt64ToUint16),
92    is_monotone = true
93)]
94fn cast_uint16_to_int64(a: u16) -> i64 {
95    i64::from(a)
96}
97
98#[sqlfunc(
99    sqlname = "uint2_to_text",
100    preserves_uniqueness = true,
101    inverse = to_unary!(super::CastStringToUint16)
102)]
103fn cast_uint16_to_string(a: u16) -> String {
104    let mut buf = String::new();
105    strconv::format_uint16(&mut buf, a);
106    buf
107}
108
109#[derive(
110    Ord,
111    PartialOrd,
112    Clone,
113    Debug,
114    Eq,
115    PartialEq,
116    Serialize,
117    Deserialize,
118    Hash
119)]
120pub struct CastUint16ToNumeric(pub Option<NumericMaxScale>);
121
122impl EagerUnaryFunc for CastUint16ToNumeric {
123    type Input<'a> = u16;
124    type Output<'a> = Result<Numeric, EvalError>;
125
126    fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> {
127        let mut a = Numeric::from(i32::from(a));
128        if let Some(scale) = self.0 {
129            if numeric::rescale(&mut a, scale.into_u8()).is_err() {
130                return Err(EvalError::NumericFieldOverflow);
131            }
132        }
133        Ok(a)
134    }
135
136    fn output_sql_type(&self, input: SqlColumnType) -> SqlColumnType {
137        SqlScalarType::Numeric { max_scale: self.0 }.nullable(input.nullable)
138    }
139
140    fn could_error(&self) -> bool {
141        self.0.is_some()
142    }
143
144    fn inverse(&self) -> Option<crate::UnaryFunc> {
145        to_unary!(super::CastNumericToUint16)
146    }
147
148    fn is_monotone(&self) -> bool {
149        true
150    }
151}
152
153impl fmt::Display for CastUint16ToNumeric {
154    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155        f.write_str("uint2_to_numeric")
156    }
157}