moosicbox_json_utils/
lib.rs1#![cfg_attr(feature = "fail-on-warnings", deny(warnings))]
7#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
8#![allow(clippy::multiple_crate_versions)]
9#![allow(clippy::module_name_repetitions)]
10
11use thiserror::Error;
12
13#[cfg(feature = "database")]
14pub mod database;
15
16#[cfg(feature = "rusqlite")]
17pub mod rusqlite;
18
19#[cfg(feature = "serde_json")]
20pub mod serde_json;
21
22#[cfg(feature = "tantivy")]
23pub mod tantivy;
24
25#[derive(Debug, Error, PartialEq, Eq)]
27pub enum ParseError {
28 #[error("Failed to parse property: {0:?}")]
30 Parse(String),
31 #[error("Failed to convert to type: {0:?}")]
33 ConvertType(String),
34 #[error("Missing required value: {0:?}")]
36 MissingValue(String),
37}
38
39pub trait ToValueType<T> {
44 fn to_value_type(self) -> Result<T, ParseError>;
50
51 fn missing_value(&self, error: ParseError) -> Result<T, ParseError> {
60 Err(error)
61 }
62}
63
64pub trait MissingValue<Type> {
69 fn missing_value(&self, error: ParseError) -> Result<Type, ParseError> {
77 Err(error)
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test_log::test]
86 fn test_parse_error_display() {
87 let err = ParseError::Parse("test property".to_string());
88 assert_eq!(
89 err.to_string(),
90 "Failed to parse property: \"test property\""
91 );
92
93 let err = ParseError::ConvertType("u64".to_string());
94 assert_eq!(err.to_string(), "Failed to convert to type: \"u64\"");
95
96 let err = ParseError::MissingValue("field_name".to_string());
97 assert_eq!(err.to_string(), "Missing required value: \"field_name\"");
98 }
99
100 #[test_log::test]
101 fn test_parse_error_eq() {
102 assert_eq!(
103 ParseError::Parse("test".to_string()),
104 ParseError::Parse("test".to_string())
105 );
106 assert_ne!(
107 ParseError::Parse("test".to_string()),
108 ParseError::Parse("other".to_string())
109 );
110 assert_ne!(
111 ParseError::Parse("test".to_string()),
112 ParseError::ConvertType("test".to_string())
113 );
114 }
115
116 struct TestValue(i32);
118
119 impl ToValueType<i32> for TestValue {
120 fn to_value_type(self) -> Result<i32, ParseError> {
121 Ok(self.0)
122 }
123 }
125
126 struct TestRow;
128
129 impl MissingValue<i32> for TestRow {
130 }
132
133 #[test_log::test]
134 fn test_to_value_type_default_missing_value_returns_error() {
135 let value = TestValue(42);
137 let error = ParseError::MissingValue("test_field".to_string());
138 let result = value.missing_value(error);
139
140 assert!(result.is_err());
141 assert_eq!(
142 result.unwrap_err(),
143 ParseError::MissingValue("test_field".to_string())
144 );
145 }
146
147 #[test_log::test]
148 fn test_missing_value_trait_default_implementation() {
149 let row = TestRow;
151 let error = ParseError::MissingValue("column_name".to_string());
152 let result: Result<i32, ParseError> = row.missing_value(error);
153
154 assert!(result.is_err());
155 assert_eq!(
156 result.unwrap_err(),
157 ParseError::MissingValue("column_name".to_string())
158 );
159 }
160}