use lib;
use super::algorithm::distance;
use super::num::Number;
use super::result::*;
#[doc(hidden)]
#[inline]
pub(crate) fn from_bytes_wrapper<T, Cb>(radix: u8, first: *const u8, last: *const u8, cb: Cb)
-> T
where Cb: FnOnce(u8, *const u8, *const u8) -> (T, *const u8, bool)
{
let (value, _, _) = cb(radix, first, last);
value
}
#[doc(hidden)]
macro_rules! generate_from_bytes_local {
($name:ident, $t:ty, $cb:ident) => (
#[inline]
fn $name(radix: u8, first: *const u8, last: *const u8)
-> ($t, *const u8, bool)
{
assert_radix!(radix);
unsafe { $cb(radix, first, last) }
}
)
}
#[doc(hidden)]
macro_rules! generate_from_range_api {
($name:ident, $t:ty, $cb:ident) => (
#[inline]
pub unsafe extern "C" fn $name(radix: u8, first: *const u8, last: *const u8)
-> $t
{
assert!(!first.is_null() || !last.is_null());
$crate::util::api::from_bytes_wrapper::<$t, _>(radix, first, last, $cb)
}
)
}
#[doc(hidden)]
macro_rules! generate_from_slice_api {
($name:ident, $t:ty, $cb:ident) => (
#[inline]
pub fn $name(radix: u8, bytes: &[u8])
-> $t
{
unsafe {
let first = bytes.as_ptr();
let last = first.add(bytes.len());
$crate::util::api::from_bytes_wrapper::<$t, _>(radix, first, last, $cb)
}
}
)
}
#[doc(hidden)]
#[inline]
pub(crate) unsafe fn try_from_bytes_wrapper<T, Cb>(radix: u8, first: *const u8, last: *const u8, cb: Cb)
-> Result<T>
where T: Number,
Cb: FnOnce(u8, *const u8, *const u8) -> (T, *const u8, bool)
{
let (value, p, overflow) = cb(radix, first, last);
if overflow {
overflow_error(value)
} else if p == last {
success(value)
} else {
let dist = if p == lib::ptr::null() { 0 } else { distance(first, p) };
invalid_digit_error(value, dist)
}
}
#[doc(hidden)]
macro_rules! generate_try_from_range_api {
($name:ident, $t:ty, $cb:ident) => (
#[inline]
pub unsafe extern "C" fn $name(radix: u8, first: *const u8, last: *const u8)
-> Result<$t>
{
assert!(!first.is_null() || !last.is_null());
$crate::util::api::try_from_bytes_wrapper::<$t, _>(radix, first, last, $cb)
}
)
}
#[doc(hidden)]
macro_rules! generate_try_from_slice_api {
($name:ident, $t:ty, $cb:ident) => (
#[inline]
pub fn $name(radix: u8, bytes: &[u8])
-> Result<$t>
{
unsafe {
let first = bytes.as_ptr();
let last = first.add(bytes.len());
$crate::util::api::try_from_bytes_wrapper::<$t, _>(radix, first, last, $cb)
}
}
)
}
#[doc(hidden)]
macro_rules! generate_to_bytes_local {
($name:ident, $t:ty, $cb:ident) => (
#[inline]
fn $name(value: $t, radix: u8, first: *mut u8, last: *mut u8)
-> *mut u8
{
assert_radix!(radix);
unsafe { $cb(value, radix, first, last) }
}
)
}
#[doc(hidden)]
macro_rules! generate_to_range_api {
($name:ident, $t:ty, $cb:ident) => (
#[inline]
pub unsafe extern "C" fn $name(value: $t, radix: u8, first: *mut u8, last: *mut u8)
-> *mut u8
{
assert!(!first.is_null() || !last.is_null());
$cb(value, radix, first, last)
}
)
}
#[doc(hidden)]
macro_rules! generate_to_slice_api {
($name:ident, $t:ty, $cb:ident) => (
#[inline]
pub fn $name<'a>(value: $t, radix: u8, bytes: &mut [u8])
-> &'a mut [u8]
{
unsafe {
let first = bytes.as_mut_ptr();
let last = first.add(bytes.len());
let last = $cb(value, radix, first, last);
$crate::lib::slice::from_raw_parts_mut(first, distance(first, last))
}
}
)
}