1pub const VARHDRSZ: i32 = 4;
9
10pub const MAX_TIME_PRECISION: i32 = 6;
12
13pub const fn char_typmod(n: i32) -> i32 {
15 n + VARHDRSZ
16}
17
18pub const fn char_length(typmod: i32) -> Option<i32> {
20 if typmod > VARHDRSZ { Some(typmod - VARHDRSZ) } else { None }
21}
22
23pub const fn numeric_typmod(precision: i32, scale: i32) -> i32 {
25 ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ
26}
27
28pub const fn numeric_precision_scale(typmod: i32) -> Option<(i32, i32)> {
30 if typmod < VARHDRSZ {
31 return None;
32 }
33 let packed = typmod - VARHDRSZ;
34 Some(((packed >> 16) & 0xffff, ((packed & 0x7ff) ^ 1024) - 1024))
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39#[repr(u8)]
40pub enum IntervalField {
41 Month = 1,
42 Year = 2,
43 Day = 3,
44 Hour = 10,
45 Minute = 11,
46 Second = 12,
47}
48
49pub const INTERVAL_FULL_RANGE: i32 = 0x7fff;
51
52pub const INTERVAL_FULL_PRECISION: i32 = 0xffff;
54
55pub fn interval_range(fields: &[IntervalField]) -> i32 {
57 fields.iter().fold(0, |mask, &field| mask | 1 << field as u8)
58}
59
60pub const fn interval_typmod(precision: i32, range: i32) -> i32 {
62 ((range & 0x7fff) << 16) | (precision & 0xffff)
63}
64
65pub const fn interval_precision_range(typmod: i32) -> Option<(i32, i32)> {
67 if typmod < 0 {
68 return None;
69 }
70 Some((typmod & 0xffff, (typmod >> 16) & 0x7fff))
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn the_typmods_match_the_table_in_the_notes() {
79 assert_eq!(char_typmod(255), 259);
80 assert_eq!(char_length(259), Some(255));
81 assert_eq!(char_length(-1), None);
82 assert_eq!(numeric_typmod(10, 2), 655366);
83 assert_eq!(numeric_precision_scale(655366), Some((10, 2)));
84 assert_eq!(numeric_precision_scale(numeric_typmod(5, -3)), Some((5, -3)));
85 assert_eq!(numeric_precision_scale(numeric_typmod(1000, 1000)), Some((1000, 1000)));
86 assert_eq!(numeric_precision_scale(-1), None);
87 let range = interval_range(&[
89 IntervalField::Day,
90 IntervalField::Hour,
91 IntervalField::Minute,
92 IntervalField::Second,
93 ]);
94 assert_eq!(interval_typmod(3, range), 470286339);
95 assert_eq!(interval_precision_range(470286339), Some((3, range)));
96 assert_eq!(interval_typmod(INTERVAL_FULL_PRECISION, INTERVAL_FULL_RANGE), 0x7fff_ffff);
97 }
98}