starchart_backends/fs/
yaml.rs

1use std::io::Read;
2
3use starchart::Entry;
4
5use super::{FsError, Transcoder};
6
7/// A transcoder for the YAML format.
8#[derive(Debug, Default, Clone, Copy)]
9#[cfg(feature = "yaml")]
10#[non_exhaustive]
11#[must_use = "transcoders do nothing by themselves"]
12pub struct YamlTranscoder;
13
14impl YamlTranscoder {
15	/// Creates a new [`YamlTranscoder`].
16	pub const fn new() -> Self {
17		Self
18	}
19}
20
21impl Transcoder for YamlTranscoder {
22	fn serialize_value<T: Entry>(&self, value: &T) -> Result<Vec<u8>, FsError> {
23		Ok(serde_yaml::to_vec(value)?)
24	}
25
26	fn deserialize_data<T: Entry, R: Read>(&self, rdr: R) -> Result<T, FsError> {
27		Ok(serde_yaml::from_reader(rdr)?)
28	}
29}
30
31#[cfg(all(test, not(miri)))]
32mod tests {
33	use std::{fmt::Debug, fs};
34
35	use starchart::backend::Backend;
36	use static_assertions::assert_impl_all;
37
38	use crate::{
39		fs::{transcoders::YamlTranscoder, FsBackend, FsError},
40		testing::{TestPath, TestSettings, TEST_GUARD},
41	};
42
43	assert_impl_all!(YamlTranscoder: Clone, Copy, Debug, Send, Sync);
44
45	#[tokio::test]
46	async fn init() -> Result<(), FsError> {
47		let _lock = TEST_GUARD.lock().await;
48		let path = TestPath::new("init", "yaml");
49		let backend = FsBackend::new(YamlTranscoder::new(), "yaml".to_owned(), &path)?;
50
51		backend.init().await?;
52
53		assert!(fs::read_dir(&path).is_ok());
54
55		Ok(())
56	}
57
58	#[tokio::test]
59	async fn table_methods() -> Result<(), FsError> {
60		let _lock = TEST_GUARD.lock().await;
61		let path = TestPath::new("table_methods", "yaml");
62		let backend = FsBackend::new(YamlTranscoder::new(), "yaml".to_owned(), &path)?;
63
64		backend.init().await?;
65
66		assert!(!backend.has_table("table").await?);
67
68		backend.create_table("table").await?;
69
70		assert!(backend.has_table("table").await?);
71
72		backend.delete_table("table").await?;
73
74		assert!(!backend.has_table("table").await?);
75
76		Ok(())
77	}
78
79	#[tokio::test]
80	async fn get_keys() -> Result<(), FsError> {
81		let _lock = TEST_GUARD.lock();
82		let path = TestPath::new("get_keys", "yaml");
83		let backend = FsBackend::new(YamlTranscoder::new(), "yaml".to_owned(), &path)?;
84
85		backend.init().await?;
86
87		backend.create_table("table").await?;
88
89		let mut settings = TestSettings::default();
90
91		backend.create("table", "1", &settings).await?;
92		settings.id = 2;
93		settings.opt = None;
94		backend.create("table", "2", &settings).await?;
95
96		let mut keys: Vec<String> = backend.get_keys("table").await?;
97
98		let mut expected = ["1".to_owned(), "2".to_owned()];
99
100		keys.sort();
101		expected.sort();
102
103		assert_eq!(keys, expected);
104
105		Ok(())
106	}
107
108	#[tokio::test]
109	async fn get_and_create() -> Result<(), FsError> {
110		let _lock = TEST_GUARD.lock().await;
111		let path = TestPath::new("get_and_create", "yaml");
112		let backend = FsBackend::new(YamlTranscoder::new(), "yaml".to_owned(), &path)?;
113
114		backend.init().await?;
115
116		backend.create_table("table").await?;
117		backend
118			.create("table", "1", &TestSettings::default())
119			.await?;
120
121		assert!(backend.get::<TestSettings>("table", "1").await?.is_some());
122
123		assert!(backend.get::<TestSettings>("table", "2").await?.is_none());
124
125		let settings = TestSettings {
126			id: 2,
127			..TestSettings::default()
128		};
129
130		assert!(backend.create("table", "2", &settings).await.is_ok());
131
132		Ok(())
133	}
134
135	#[tokio::test]
136	async fn update_and_delete() -> Result<(), FsError> {
137		let _lock = TEST_GUARD.lock().await;
138		let path = TestPath::new("update_and_delete", "yaml");
139		let backend = FsBackend::new(YamlTranscoder::new(), "yaml".to_owned(), &path)?;
140
141		backend.init().await?;
142
143		backend.create_table("table").await?;
144
145		let mut settings = TestSettings::default();
146
147		backend.create("table", "1", &settings).await?;
148
149		settings.opt = None;
150
151		backend.update("table", "1", &settings).await?;
152
153		assert_eq!(
154			backend.get::<TestSettings>("table", "1").await?,
155			Some(settings)
156		);
157
158		backend.delete("table", "1").await?;
159
160		assert_eq!(backend.get::<TestSettings>("table", "1").await?, None);
161
162		Ok(())
163	}
164}