• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::libyaml::cstr::CStr;
2 use std::fmt::{self, Debug, Display};
3 use std::mem::MaybeUninit;
4 use std::ptr::NonNull;
5 use unsafe_libyaml as sys;
6 
7 pub(crate) type Result<T> = std::result::Result<T, Error>;
8 
9 pub(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 
18 impl Error {
parse_error(parser: *const sys::yaml_parser_t) -> Self19     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 
emit_error(emitter: *const sys::yaml_emitter_t) -> Self40     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 
mark(&self) -> Mark60     pub fn mark(&self) -> Mark {
61         self.problem_mark
62     }
63 }
64 
65 impl Display for Error {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result66     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 
86 impl Debug for Error {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result87     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)]
118 pub(crate) struct Mark {
119     pub(super) sys: sys::yaml_mark_t,
120 }
121 
122 impl Mark {
index(&self) -> u64123     pub fn index(&self) -> u64 {
124         self.sys.index
125     }
126 
line(&self) -> u64127     pub fn line(&self) -> u64 {
128         self.sys.line
129     }
130 
column(&self) -> u64131     pub fn column(&self) -> u64 {
132         self.sys.column
133     }
134 }
135 
136 impl Display for Mark {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result137     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 
151 impl Debug for Mark {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result152     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 }
163