use crate ::libyaml::cstr::CStr;
use std::fmt::{self , Debug, Display};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
use unsafe_libyaml as sys;
pub (crate ) type Result<T> = std::result::Result<T, Error>;
pub (crate ) struct Error {
kind: sys::yaml_error_type_t,
problem: CStr<'static>,
problem_offset: u64,
problem_mark: Mark,
context: Option<CStr<'static>>,
context_mark: Mark,
}
impl Error {
pub unsafe fn parse_error(parser: *const sys::yaml_parser_t) -> Self {
Error {
kind: unsafe { (*parser).error },
problem: match NonNull::new(unsafe { (*parser).problem as *mut _ }) {
Some(problem) => unsafe { CStr::from_ptr(problem) },
None => CStr::from_bytes_with_nul(b"libyaml parser failed but there is no error\0" ),
},
problem_offset: unsafe { (*parser).problem_offset },
problem_mark: Mark {
sys: unsafe { (*parser).problem_mark },
},
context: match NonNull::new(unsafe { (*parser).context as *mut _ }) {
Some(context) => Some(unsafe { CStr::from_ptr(context) }),
None => None,
},
context_mark: Mark {
sys: unsafe { (*parser).context_mark },
},
}
}
pub unsafe fn emit_error(emitter: *const sys::yaml_emitter_t) -> Self {
Error {
kind: unsafe { (*emitter).error },
problem: match NonNull::new(unsafe { (*emitter).problem as *mut _ }) {
Some(problem) => unsafe { CStr::from_ptr(problem) },
None => {
CStr::from_bytes_with_nul(b"libyaml emitter failed but there is no error\0" )
}
},
problem_offset: 0 ,
problem_mark: Mark {
sys: unsafe { MaybeUninit::<sys::yaml_mark_t>::zeroed().assume_init() },
},
context: None,
context_mark: Mark {
sys: unsafe { MaybeUninit::<sys::yaml_mark_t>::zeroed().assume_init() },
},
}
}
pub fn mark(&self ) -> Mark {
self .problem_mark
}
}
impl Display for Error {
fn fmt(&self , formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}" , self .problem)?;
if self .problem_mark.sys.line != 0 || self .problem_mark.sys.column != 0 {
write!(formatter, " at {}" , self .problem_mark)?;
} else if self .problem_offset != 0 {
write!(formatter, " at position {}" , self .problem_offset)?;
}
if let Some(context) = &self .context {
write!(formatter, ", {}" , context)?;
if (self .context_mark.sys.line != 0 || self .context_mark.sys.column != 0 )
&& (self .context_mark.sys.line != self .problem_mark.sys.line
|| self .context_mark.sys.column != self .problem_mark.sys.column)
{
write!(formatter, " at {}" , self .context_mark)?;
}
}
Ok(())
}
}
impl Debug for Error {
fn fmt(&self , formatter: &mut fmt::Formatter) -> fmt::Result {
let mut formatter = formatter.debug_struct("Error" );
if let Some(kind) = match self .kind {
sys::YAML_MEMORY_ERROR => Some("MEMORY" ),
sys::YAML_READER_ERROR => Some("READER" ),
sys::YAML_SCANNER_ERROR => Some("SCANNER" ),
sys::YAML_PARSER_ERROR => Some("PARSER" ),
sys::YAML_COMPOSER_ERROR => Some("COMPOSER" ),
sys::YAML_WRITER_ERROR => Some("WRITER" ),
sys::YAML_EMITTER_ERROR => Some("EMITTER" ),
_ => None,
} {
formatter.field("kind" , &format_args!("{}" , kind));
}
formatter.field("problem" , &self .problem);
if self .problem_mark.sys.line != 0 || self .problem_mark.sys.column != 0 {
formatter.field("problem_mark" , &self .problem_mark);
} else if self .problem_offset != 0 {
formatter.field("problem_offset" , &self .problem_offset);
}
if let Some(context) = &self .context {
formatter.field("context" , context);
if self .context_mark.sys.line != 0 || self .context_mark.sys.column != 0 {
formatter.field("context_mark" , &self .context_mark);
}
}
formatter.finish()
}
}
#[ derive(Copy, Clone)]
pub (crate ) struct Mark {
pub (super ) sys: sys::yaml_mark_t,
}
impl Mark {
pub fn index(&self ) -> u64 {
self .sys.index
}
pub fn line(&self ) -> u64 {
self .sys.line
}
pub fn column(&self ) -> u64 {
self .sys.column
}
}
impl Display for Mark {
fn fmt(&self , formatter: &mut fmt::Formatter) -> fmt::Result {
if self .sys.line != 0 || self .sys.column != 0 {
write!(
formatter,
"line {} column {}" ,
self .sys.line + 1 ,
self .sys.column + 1 ,
)
} else {
write!(formatter, "position {}" , self .sys.index)
}
}
}
impl Debug for Mark {
fn fmt(&self , formatter: &mut fmt::Formatter) -> fmt::Result {
let mut formatter = formatter.debug_struct("Mark" );
if self .sys.line != 0 || self .sys.column != 0 {
formatter.field("line" , &(self .sys.line + 1 ));
formatter.field("column" , &(self .sys.column + 1 ));
} else {
formatter.field("index" , &self .sys.index);
}
formatter.finish()
}
}
Messung V0.5 in Prozent C=100 H=80 G=90
¤ Dauer der Verarbeitung: 0.4 Sekunden
¤
*© Formatika GbR, Deutschland