use crate::ptr::Ptr;
use crate::types::builder::Builder;
use crate::types::conversion_error::ConversionError;
use crate::types::owner::Owner;
use crate::types::sci::Sci;
use crate::types::sign::Sign;
use alloc::string::String;
use core::str::FromStr;
impl Sci {
pub(crate) fn from_string(mut data: String) -> Result<Sci, ConversionError> {
let len = data.len() as isize;
let mut data_start = Ptr::new_mut(unsafe { data.as_bytes_mut() });
let data_end = data_start.offset(len);
if data_start == data_end {
return Err(ConversionError::ParseError);
}
let next = *data_start as u8;
let sign = Sign::new(next == b'-');
if sign.is_negative() || next == b'+' {
data_start.inc();
}
if data_start == data_end {
return Err(ConversionError::ParseError);
}
let next = *data_start as u8;
if !((b'0'..=b'9').contains(&next) || next == b'.') {
return Err(ConversionError::ParseError);
}
let mut data_ptr = data_start;
while data_ptr != data_end {
let next = *data_ptr as u8;
if !(b'0'..=b'9').contains(&next) {
break;
}
*data_ptr = (next & 0x0f) as i8; data_ptr.inc();
}
let mut mantissa_end = data_ptr;
let mut dot_len = 0;
let exponent_start;
let exponent_len;
if data_ptr == data_end {
exponent_start = data_end;
exponent_len = 0;
} else {
let next = *data_ptr as u8;
if next == b'.' {
data_ptr.inc();
while data_ptr != data_end {
let next = *data_ptr as u8;
if !(b'0'..=b'9').contains(&next) {
break;
}
*mantissa_end = (next & 0x0f) as i8; mantissa_end.inc();
data_ptr.inc();
dot_len += 1;
}
}
if data_ptr == data_end {
exponent_start = data_end;
exponent_len = 0;
} else {
let next = *data_ptr as u8;
if !(next == b'e' || next == b'E') {
return Err(ConversionError::ParseError);
}
data_ptr.inc();
exponent_start = data_ptr;
exponent_len = data_end.offset_from(data_ptr);
if exponent_len == 0 {
return Err(ConversionError::ParseError);
}
}
}
let exponent = if exponent_len == 0 {
0
} else {
isize::from_str(unsafe {
core::str::from_utf8_unchecked(core::slice::from_raw_parts(
exponent_start.as_slice(exponent_len).as_ptr(),
exponent_len as usize,
))
})
.map_err(|_| ConversionError::ParseError)?
};
if data_start == mantissa_end {
return Err(ConversionError::ParseError);
}
let len = mantissa_end.offset_from(data_start);
Ok(
Builder::new_with_data(
sign,
data_start,
len,
exponent - dot_len,
Owner::new_string(data),
)
.finish(),
)
}
}