1use std::ffi::CStr;
2
3use num_derive::FromPrimitive;
4
5use yyjson_sys as ffi;
6
7#[derive(Debug)]
8pub enum ReadError {
9 OnCreateErr(&'static str),
10 OnRead {
11 code: ReadCode,
12 msg: &'static str,
13 pos: usize,
14 },
15}
16
17impl std::fmt::Display for ReadError {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 use ReadError::*;
20 match self {
21 OnCreateErr(s) => write!(f, "On create error: {}", s),
22 OnRead { code, msg, pos } => {
23 write!(f, "{:?} at pos {pos}: {}", code, msg)
24 }
25 }
26 }
27}
28
29impl std::error::Error for ReadError {}
30
31#[derive(Debug, FromPrimitive, PartialEq)]
32#[repr(u32)]
33pub enum ReadCode {
34 Success = 0,
35 ErrorInvalidParameter = 1,
36 ErrorMemoryAllocation = 2,
37 ErrorEmptyContent = 3,
38 ErrorUnexpectedContent = 4,
39 ErrorUnexpectedEnd = 5,
40 ErrorUnexpectedCharacter = 6,
41 ErrorJsonStructure = 7,
42 ErrorInvalidComment = 8,
43 ErrorInvalidNumber = 9,
44 ErrorInvalidString = 10,
45 ErrorLiteral = 11,
46 ErrorFileOpen = 12,
47 ErrorFileRead = 13,
48}
49
50impl ReadError {
51 #[inline(always)]
52 pub fn is_mem_allocation_err(&self) -> bool {
53 match self {
54 Self::OnRead { code, .. } => code == &ReadCode::ErrorMemoryAllocation,
55 _ => false,
56 }
57 }
58}
59
60impl From<&ffi::yyjson_read_err> for ReadError {
61 fn from(v: &ffi::yyjson_read_err) -> Self {
62 use ReadError::*;
63 let code: ReadCode = match num_traits::cast::FromPrimitive::from_u32(v.code) {
64 Some(v) => v,
65 None => return OnCreateErr("yyjson_read_code should be in range 0..=13"),
66 };
67
68 if code == ReadCode::Success {
69 return OnCreateErr("yyjson_read_code is SUCCESS (non-error)");
70 }
71
72 if v.msg.is_null() {
73 return OnCreateErr("error msg string is null yet error occured");
74 }
75
76 let msg = {
80 let as_c_str = unsafe { CStr::from_ptr(v.msg) };
81 match as_c_str.to_str() {
82 Ok(s) => s,
83 Err(_) => return OnCreateErr("error msg string is invalid utf-8"),
84 }
85 };
86
87 OnRead {
88 code,
89 msg,
90 pos: v.pos,
91 }
92 }
93}
94
95#[derive(Debug, Default)]
96pub struct ReadOptions {
97 pub stop_when_done: bool,
101 pub allow_trailing_commas: bool,
102 pub allow_comments: bool,
103 pub allow_inf_and_nan: bool,
104 pub bignums_as_raw_strings: bool,
105}
106
107impl ReadOptions {
108 pub fn to_read_flag(&self) -> u32 {
109 use ffi::*;
110 let mut flag: u32 = YYJSON_READ_NOFLAG;
111 if self.stop_when_done {
112 flag |= YYJSON_READ_STOP_WHEN_DONE;
113 }
114 if self.allow_trailing_commas {
115 flag |= YYJSON_READ_ALLOW_TRAILING_COMMAS;
116 }
117 if self.allow_comments {
118 flag |= YYJSON_READ_ALLOW_COMMENTS;
119 }
120 if self.allow_inf_and_nan {
121 flag |= YYJSON_READ_ALLOW_INF_AND_NAN;
122 }
123 if self.bignums_as_raw_strings {
124 flag |= YYJSON_READ_BIGNUM_AS_RAW;
125 }
126 return flag;
127 }
128}