serde_yaml/libyaml/
error.rs
1use crate::libyaml::cstr::CStr;
2use std::fmt::{self, Debug, Display};
3use std::mem::MaybeUninit;
4use std::ptr::NonNull;
5use unsafe_libyaml as sys;
6
7pub(crate) type Result<T> = std::result::Result<T, Error>;
8
9pub(crate) struct Error {
10 kind: sys::yaml_error_type_t,
11 problem: CStr<'static>,
12 problem_offset: u64,
13 problem_mark: Mark,
14 context: Option<CStr<'static>>,
15 context_mark: Mark,
16}
17
18impl Error {
19 pub unsafe fn parse_error(parser: *const sys::yaml_parser_t) -> Self {
20 Error {
21 kind: unsafe { (*parser).error },
22 problem: match NonNull::new(unsafe { (*parser).problem as *mut _ }) {
23 Some(problem) => unsafe { CStr::from_ptr(problem) },
24 None => CStr::from_bytes_with_nul(b"libyaml parser failed but there is no error\0"),
25 },
26 problem_offset: unsafe { (*parser).problem_offset },
27 problem_mark: Mark {
28 sys: unsafe { (*parser).problem_mark },
29 },
30 context: match NonNull::new(unsafe { (*parser).context as *mut _ }) {
31 Some(context) => Some(unsafe { CStr::from_ptr(context) }),
32 None => None,
33 },
34 context_mark: Mark {
35 sys: unsafe { (*parser).context_mark },
36 },
37 }
38 }
39
40 pub unsafe fn emit_error(emitter: *const sys::yaml_emitter_t) -> Self {
41 Error {
42 kind: unsafe { (*emitter).error },
43 problem: match NonNull::new(unsafe { (*emitter).problem as *mut _ }) {
44 Some(problem) => unsafe { CStr::from_ptr(problem) },
45 None => {
46 CStr::from_bytes_with_nul(b"libyaml emitter failed but there is no error\0")
47 }
48 },
49 problem_offset: 0,
50 problem_mark: Mark {
51 sys: unsafe { MaybeUninit::<sys::yaml_mark_t>::zeroed().assume_init() },
52 },
53 context: None,
54 context_mark: Mark {
55 sys: unsafe { MaybeUninit::<sys::yaml_mark_t>::zeroed().assume_init() },
56 },
57 }
58 }
59
60 pub fn mark(&self) -> Mark {
61 self.problem_mark
62 }
63}
64
65impl Display for Error {
66 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
67 write!(formatter, "{}", self.problem)?;
68 if self.problem_mark.sys.line != 0 || self.problem_mark.sys.column != 0 {
69 write!(formatter, " at {}", self.problem_mark)?;
70 } else if self.problem_offset != 0 {
71 write!(formatter, " at position {}", self.problem_offset)?;
72 }
73 if let Some(context) = &self.context {
74 write!(formatter, ", {}", context)?;
75 if (self.context_mark.sys.line != 0 || self.context_mark.sys.column != 0)
76 && (self.context_mark.sys.line != self.problem_mark.sys.line
77 || self.context_mark.sys.column != self.problem_mark.sys.column)
78 {
79 write!(formatter, " at {}", self.context_mark)?;
80 }
81 }
82 Ok(())
83 }
84}
85
86impl Debug for Error {
87 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
88 let mut formatter = formatter.debug_struct("Error");
89 if let Some(kind) = match self.kind {
90 sys::YAML_MEMORY_ERROR => Some("MEMORY"),
91 sys::YAML_READER_ERROR => Some("READER"),
92 sys::YAML_SCANNER_ERROR => Some("SCANNER"),
93 sys::YAML_PARSER_ERROR => Some("PARSER"),
94 sys::YAML_COMPOSER_ERROR => Some("COMPOSER"),
95 sys::YAML_WRITER_ERROR => Some("WRITER"),
96 sys::YAML_EMITTER_ERROR => Some("EMITTER"),
97 _ => None,
98 } {
99 formatter.field("kind", &format_args!("{}", kind));
100 }
101 formatter.field("problem", &self.problem);
102 if self.problem_mark.sys.line != 0 || self.problem_mark.sys.column != 0 {
103 formatter.field("problem_mark", &self.problem_mark);
104 } else if self.problem_offset != 0 {
105 formatter.field("problem_offset", &self.problem_offset);
106 }
107 if let Some(context) = &self.context {
108 formatter.field("context", context);
109 if self.context_mark.sys.line != 0 || self.context_mark.sys.column != 0 {
110 formatter.field("context_mark", &self.context_mark);
111 }
112 }
113 formatter.finish()
114 }
115}
116
117#[derive(Copy, Clone)]
118pub(crate) struct Mark {
119 pub(super) sys: sys::yaml_mark_t,
120}
121
122impl Mark {
123 pub fn index(&self) -> u64 {
124 self.sys.index
125 }
126
127 pub fn line(&self) -> u64 {
128 self.sys.line
129 }
130
131 pub fn column(&self) -> u64 {
132 self.sys.column
133 }
134}
135
136impl Display for Mark {
137 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
138 if self.sys.line != 0 || self.sys.column != 0 {
139 write!(
140 formatter,
141 "line {} column {}",
142 self.sys.line + 1,
143 self.sys.column + 1,
144 )
145 } else {
146 write!(formatter, "position {}", self.sys.index)
147 }
148 }
149}
150
151impl Debug for Mark {
152 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
153 let mut formatter = formatter.debug_struct("Mark");
154 if self.sys.line != 0 || self.sys.column != 0 {
155 formatter.field("line", &(self.sys.line + 1));
156 formatter.field("column", &(self.sys.column + 1));
157 } else {
158 formatter.field("index", &self.sys.index);
159 }
160 formatter.finish()
161 }
162}