///|
pub(all) struct FieldCursor {
fields_value : Array[String]
record_index_value : Int
} derive(Debug)
///|
fn field_error(
code : NmeaErrorCode,
index : Int,
message : String,
) -> NmeaError {
NmeaError::from_diagnostic(
Diagnostic::new(code, Error, message, SourceRef::field(0, index)),
)
}
///|
pub fn FieldCursor::new(
fields : Array[String],
record_index? : Int = 0,
) -> FieldCursor {
{ fields_value: fields.copy(), record_index_value: record_index }
}
///|
pub fn FieldCursor::length(self : FieldCursor) -> Int {
self.fields_value.length()
}
///|
pub fn FieldCursor::record_index(self : FieldCursor) -> Int {
self.record_index_value
}
///|
fn FieldCursor::at(
self : FieldCursor,
index : Int,
) -> Result[String, NmeaError] {
if index < 0 || index >= self.fields_value.length() {
return Err(field_error(FieldMissing, index, "required field is missing"))
}
Ok(self.fields_value[index])
}
///|
pub fn FieldCursor::required(
self : FieldCursor,
index : Int,
) -> Result[String, NmeaError] {
let value = match self.at(index) {
Ok(value) => value
Err(error) => return Err(error)
}
if value.length() == 0 {
return Err(field_error(FieldEmpty, index, "required field is empty"))
}
Ok(value)
}
///|
pub fn FieldCursor::optional(
self : FieldCursor,
index : Int,
) -> Result[String?, NmeaError] {
if index < 0 || index >= self.fields_value.length() {
return Ok(None)
}
let value = self.fields_value[index]
if value.length() == 0 {
Ok(None)
} else {
Ok(Some(value))
}
}
///|
fn parse_integer_text(value : String, index : Int) -> Result[Int, NmeaError] {
if value.length() == 0 {
return Err(field_error(FieldEmpty, index, "integer field is empty"))
}
let mut cursor = 0
let mut negative = false
if value[0].to_int() == 45 {
negative = true
cursor = 1
} else if value[0].to_int() == 43 {
cursor = 1
}
if cursor >= value.length() {
return Err(field_error(FieldInvalidInteger, index, "integer has no digits"))
}
let mut result = 0
while cursor < value.length() {
let code = value[cursor].to_int()
if code < 48 || code > 57 {
return Err(
field_error(FieldInvalidInteger, index, "integer contains a non-digit"),
)
}
result = result * 10 + code - 48
cursor = cursor + 1
}
Ok(if negative { -result } else { result })
}
///|
pub fn FieldCursor::integer(
self : FieldCursor,
index : Int,
min? : Int = -2147483648,
max? : Int = 2147483647,
) -> Result[Int, NmeaError] {
let value = match self.required(index) {
Ok(value) => value
Err(error) => return Err(error)
}
let result = match parse_integer_text(value, index) {
Ok(value) => value
Err(error) => return Err(error)
}
if result < min {
return Err(
field_error(
FieldInvalidInteger,
index,
"integer is below the lower bound",
),
)
}
if result > max {
return Err(
field_error(FieldInvalidInteger, index, "integer exceeds the upper bound"),
)
}
Ok(result)
}
///|
pub fn FieldCursor::decimal(
self : FieldCursor,
index : Int,
max_scale? : Int = 9,
) -> Result[ExactDecimal, NmeaError] {
let value = match self.required(index) {
Ok(value) => value
Err(error) => return Err(error)
}
match ExactDecimal::parse(value, max_scale~) {
Ok(result) => Ok(result)
Err(_) =>
Err(
field_error(FieldInvalidDecimal, index, "field is not a valid decimal"),
)
}
}