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