use rupg_common::{Error, Result, SqlState};
use rupg_types::{self as types, Value};
use crate::{Call, Kernel, bad_value};
const MAC6: u64 = 0xffff_ffff_ffff;
pub(crate) fn by_src(src: &str) -> Option<Kernel> {
Some(match src {
"macaddr_trunc" => macaddr_trunc,
"macaddr8_trunc" => macaddr8_trunc,
"macaddr_not" => macaddr_not,
"macaddr8_not" => macaddr8_not,
"macaddr_and" | "macaddr8_and" => and,
"macaddr_or" | "macaddr8_or" => or,
"macaddr8_set7bit" => set7bit,
"macaddrtomacaddr8" => to_macaddr8,
"macaddr8tomacaddr" => to_macaddr,
_ => return None,
})
}
fn bits(args: &[Value], n: usize) -> Result<u64> {
match args.get(n) {
Some(Value::Int8(v)) => Ok(v.cast_unsigned()),
_ => Err(bad_value()),
}
}
fn value(bits: u64) -> Value {
Value::Int8(bits.cast_signed())
}
fn macaddr_trunc(_: &Call<'_>, args: &[Value]) -> Result<Value> {
Ok(value(bits(args, 0)? & 0xffff_ff00_0000))
}
fn macaddr8_trunc(_: &Call<'_>, args: &[Value]) -> Result<Value> {
Ok(value(bits(args, 0)? & 0xffff_ff00_0000_0000))
}
fn macaddr_not(_: &Call<'_>, args: &[Value]) -> Result<Value> {
Ok(value(!bits(args, 0)? & MAC6))
}
fn macaddr8_not(_: &Call<'_>, args: &[Value]) -> Result<Value> {
Ok(value(!bits(args, 0)?))
}
fn and(_: &Call<'_>, args: &[Value]) -> Result<Value> {
Ok(value(bits(args, 0)? & bits(args, 1)?))
}
fn or(_: &Call<'_>, args: &[Value]) -> Result<Value> {
Ok(value(bits(args, 0)? | bits(args, 1)?))
}
fn set7bit(_: &Call<'_>, args: &[Value]) -> Result<Value> {
Ok(value(bits(args, 0)? | 0x0200_0000_0000_0000))
}
fn to_macaddr8(_: &Call<'_>, args: &[Value]) -> Result<Value> {
Ok(value(types::macaddr_to_macaddr8(bits(args, 0)?)))
}
fn to_macaddr(_: &Call<'_>, args: &[Value]) -> Result<Value> {
types::macaddr8_to_macaddr(bits(args, 0)?).map(value).ok_or_else(|| {
Error::new(
SqlState::NUMERIC_VALUE_OUT_OF_RANGE,
"macaddr8 data out of range to convert to macaddr",
)
.with_hint(
"Only addresses that have FF and FE as values in the 4th and 5th bytes from the left, for example xx:xx:xx:ff:fe:xx:xx:xx, are eligible to be converted from macaddr8 to macaddr.",
)
})
}