risingwave_expr_impl/scalar/
bytea_bits.rs1use risingwave_expr::{ExprError, Result, function};
16
17#[function("get_bit(bytea, int8) -> int4")]
28pub fn get_bit(bytes: &[u8], n: i64) -> Result<i32> {
29    let max_sz = (bytes.len() * 8) as i64;
30    if n < 0 || n >= max_sz {
31        return Err(ExprError::InvalidParam {
32            name: "get_bit",
33            reason: format!("index {} out of valid range, 0..{}", n, max_sz - 1).into(),
34        });
35    }
36    let index = n / 8;
37    let byte = bytes[index as usize];
38    Ok(((byte >> (n % 8)) & 1) as i32)
39}
40
41#[function("set_bit(bytea, int8, int4) -> bytea")]
52pub fn set_bit(bytes: &[u8], n: i64, value: i32) -> Result<Box<[u8]>> {
53    let max_sz = (bytes.len() * 8) as i64;
54    if n < 0 || n >= max_sz {
55        return Err(ExprError::InvalidParam {
56            name: "set_bit",
57            reason: format!("index {} out of valid range, 0..{}", n, max_sz - 1).into(),
58        });
59    }
60
61    if value != 0 && value != 1 {
62        return Err(ExprError::InvalidParam {
63            name: "set_bit",
64            reason: format!("value {} is invalid, new bit must be 0 or 1", value).into(),
65        });
66    }
67
68    let mut buf = bytes.to_vec();
69    let index = (n / 8) as usize;
70    let bit_pos = (n % 8) as u8;
71
72    if value != 0 {
73        buf[index] |= 1 << bit_pos;
74    } else {
75        buf[index] &= !(1 << bit_pos);
76    }
77    Ok(buf.into_boxed_slice())
78}
79
80#[function("get_byte(bytea, int4) -> int4")]
91pub fn get_byte(bytes: &[u8], n: i32) -> Result<i32> {
92    let max_sz = bytes.len() as i32;
93    if n < 0 || n >= max_sz {
94        return Err(ExprError::InvalidParam {
95            name: "get_byte",
96            reason: format!("index {} out of valid range, 0..{}", n, max_sz - 1).into(),
97        });
98    }
99    Ok(bytes[n as usize].into())
100}
101
102#[function("set_byte(bytea, int4, int4) -> bytea")]
113pub fn set_byte(bytes: &[u8], n: i32, value: i32) -> Result<Box<[u8]>> {
114    let max_sz = bytes.len() as i32;
115    if n < 0 || n >= max_sz {
116        return Err(ExprError::InvalidParam {
117            name: "set_byte",
118            reason: format!("index {} out of valid range, 0..{}", n, max_sz - 1).into(),
119        });
120    }
121    let mut buf = bytes.to_vec();
122    buf[n as usize] = value as u8;
123    Ok(buf.into_boxed_slice())
124}
125
126#[function("bit_count(bytea) -> int8")]
137pub fn bit_count(bytes: &[u8]) -> i64 {
138    let mut ans = 0;
139    for byte in bytes {
140        ans += byte.count_ones();
141    }
142    ans.into()
143}
144
145#[function("reverse(bytea) -> bytea")]
156pub fn reverse_bytea(bytes: &[u8]) -> Box<[u8]> {
157    bytes
158        .iter()
159        .rev()
160        .copied()
161        .collect::<Vec<_>>()
162        .into_boxed_slice()
163}