ason/lib.rs
1// Copyright (c) 2024 Hemashushu <hippospark@gmail.com>, All rights reserved.
2//
3// This Source Code Form is subject to the terms of
4// the Mozilla Public License version 2.0 and additional exceptions,
5// more details in file LICENSE, LICENSE.additional and CONTRIBUTING.
6
7pub mod ast;
8mod charstream;
9mod charwithposition;
10mod errorprinter;
11mod lexer;
12mod location;
13mod normalizer;
14mod parser;
15mod peekableiter;
16mod printer;
17mod serde;
18mod token;
19
20pub use parser::parse_from_reader;
21pub use parser::parse_from_str;
22pub use printer::print_to_string;
23pub use printer::print_to_writer;
24
25pub use serde::de::from_reader;
26pub use serde::de::from_str;
27pub use serde::ser::to_string;
28pub use serde::ser::to_writer;
29pub use serde::serde_date::Date;
30
31use std::fmt::{self, Display};
32
33use crate::location::Location;
34
35#[derive(Debug, PartialEq, Clone)]
36pub enum AsonError {
37 Message(String),
38 UnexpectedEndOfDocument(String),
39
40 // note that the "index" (and the result of "index+length") may exceed
41 // the last index of string, for example, the "char incomplete" error raised by a string `'a`,
42 // which index is 2.
43 MessageWithLocation(String, Location),
44}
45
46impl Display for AsonError {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 match self {
49 AsonError::Message(msg) => f.write_str(msg),
50 AsonError::UnexpectedEndOfDocument(detail) => {
51 writeln!(f, "Unexpected to reach the end of document.")?;
52 write!(f, "{}", detail)
53 }
54 AsonError::MessageWithLocation(detail, location) => {
55 writeln!(
56 f,
57 "Error at line: {}, column: {}",
58 location.line + 1,
59 location.column + 1
60 )?;
61 write!(f, "{}", detail)
62 }
63 }
64 }
65}
66
67impl std::error::Error for AsonError {}
68
69// #[cfg(test)]
70// mod tests {
71// use std::collections::HashMap;
72//
73// use serde::{Deserialize, Serialize};
74//
75// use crate::{
76// ast::{AsonNode, KeyValuePair, Number},
77// from_str, parse_from_str, print_to_string, to_string,
78// };
79// use pretty_assertions::assert_eq;
80//
81// #[test]
82// fn test_from_str_and_to_string() {
83// #[derive(Debug, PartialEq, Serialize, Deserialize)]
84// struct Package {
85// name: String,
86//
87// #[serde(rename = "type")]
88// type_: Type,
89//
90// version: String,
91// dependencies: HashMap<String, Option<String>>,
92// }
93//
94// #[derive(Debug, PartialEq, Serialize, Deserialize)]
95// enum Type {
96// Application,
97// Library,
98// }
99//
100// let text = r#"{
101// name: "foo"
102// type: Type::Application
103// version: "0.1.0"
104// dependencies: {
105// "random": Option::None
106// "regex": Option::Some("1.0.1")
107// }
108// }"#;
109//
110// let package = from_str::<Package>(text).unwrap();
111// assert_eq!(package.name, "foo");
112// assert_eq!(package.type_, Type::Application);
113// assert_eq!(package.version, "0.1.0");
114// assert_eq!(package.dependencies.get("random").unwrap(), &None);
115// assert_eq!(
116// package.dependencies.get("regex").unwrap(),
117// &Some("1.0.1".to_owned())
118// );
119//
120// // test `to_string`
121//
122// let s = to_string(&package).unwrap();
123// assert!(s.starts_with("{"));
124// assert!(s.ends_with("}"));
125// assert!(s.contains(r#"name: "foo""#));
126// assert!(s.contains(r#"type: Type::Application"#));
127// assert!(s.contains(r#"version: "0.1.0""#));
128// assert!(s.contains(r#"dependencies: {"#));
129// assert!(s.contains(r#""random": Option::None"#));
130// assert!(s.contains(r#""regex": Option::Some("1.0.1")"#));
131// }
132//
133// #[test]
134// fn test_parse_from_and_print_to() {
135// let text = r#"{
136// id: 123
137// name: "John"
138// orders: [
139// 11
140// 13
141// ]
142// }"#;
143//
144// let node = parse_from_str(text).unwrap();
145//
146// assert_eq!(
147// node,
148// AsonNode::Object(vec![
149// KeyValuePair {
150// key: String::from("id"),
151// value: Box::new(AsonNode::Number(Number::I32(123)))
152// },
153// KeyValuePair {
154// key: String::from("name"),
155// value: Box::new(AsonNode::String(String::from("John")))
156// },
157// KeyValuePair {
158// key: String::from("orders"),
159// value: Box::new(AsonNode::List(vec![
160// AsonNode::Number(Number::I32(11)),
161// AsonNode::Number(Number::I32(13))
162// ]))
163// }
164// ])
165// );
166//
167// // test `print_to_string`
168// let s = print_to_string(&node);
169// assert_eq!(s, text);
170// }
171// }