use super::keypath::{Keypath, LeafKey};
use crate::exn::nnint_overflow;
use crate::sys_exn::nnint::*;
use crate::sys_exn::nnint_internal as nnint;
use core::fmt::Debug;
#[derive(Debug)]
pub struct NNInt {
key: LeafKey,
}
impl From<Keypath> for NNInt {
fn from(keypath: Keypath) -> Self {
Self {
key: LeafKey::from(keypath),
}
}
}
impl NNInt {
pub fn get(&self) -> i128 {
non_negative_int_get(self.key.get())
}
pub fn try_get(&self) -> Result<i128, crate::exn::LibraryExn> {
non_negative_int_try_get(self.key.get())
}
pub fn set(&mut self, set_value: i128) {
nnint::set_add(
self.key.get(),
Some(set_value),
0,
self.key.is_exclusive(),
);
}
pub fn inc(&mut self, increment: i128) {
let key = self.key.get();
let (s, a) = nnint::get_values(key);
let add_value =
a.checked_add(increment).unwrap_or_else(|| nnint_overflow());
nnint::set_add(key, s, add_value, self.key.is_exclusive());
}
pub fn strict_inc(&mut self, increment: i128) {
use crate::re_throw::OrReThrow;
self.try_strict_inc(increment).or_re_throw()
}
pub fn try_strict_inc(
&mut self,
increment: i128,
) -> Result<(), crate::exn::LibraryExn> {
use crate::exn::LibraryExn;
let key = self.key.get();
let (s, a) = match nnint::try_get_values_force(key) {
Ok(values) => values,
Err(e) if e.is_storage_missing() => (0, 0),
Err(e) => return Err(e),
};
let add_value = a
.checked_add(increment)
.ok_or(LibraryExn::NonNegativeIntOverflow)?;
let total = s
.checked_add(add_value)
.ok_or(LibraryExn::NonNegativeIntOverflow)?;
if total < 0 {
return Err(LibraryExn::NonNegativeIntUnderflow);
}
nnint::try_set_add(key, Some(s), add_value, self.key.is_exclusive())
}
}
impl super::sealed::Sealed for NNInt {}
impl super::node::StorageType for NNInt {}
impl super::flags::Flaggable for NNInt {
fn storage_key(&self) -> &crate::types::StorageKey {
self.key.get()
}
}
impl super::deletable::Deletable for NNInt {
fn delete_internal(&mut self, exclusive: bool) {
let exclusive = exclusive || self.key.is_exclusive();
crate::sys_exn::delete::delete(self.key.get(), exclusive);
}
}