1#![no_std]
31#![warn(missing_docs)]
32
33extern crate alloc;
34
35use alloc::borrow::Cow;
36use alloc::string::ToString;
37
38pub mod binary;
39pub mod error;
40pub mod text;
41pub mod value;
42
43pub use error::{Error, Result};
44pub use value::{Obj, Value, Vdf};
45
46pub use binary::{InvalidUtf8, ParseOptions};
48pub use text::parse_text;
49
50pub fn parse_binary(input: &[u8]) -> Result<Vdf<'_>> {
58 binary::parse(input)
59}
60
61pub fn parse_binary_with(input: &[u8], options: ParseOptions) -> Result<Vdf<'_>> {
63 binary::parse_with(input, options)
64}
65
66pub fn parse_shortcuts(input: &[u8]) -> Result<Vdf<'_>> {
74 binary::parse_shortcuts(input)
75}
76
77pub fn parse_shortcuts_with(input: &[u8], options: ParseOptions) -> Result<Vdf<'_>> {
79 binary::parse_shortcuts_with(input, options)
80}
81
82pub fn parse_appinfo(input: &[u8]) -> Result<Vdf<'_>> {
90 binary::parse_appinfo(input)
91}
92
93pub fn parse_appinfo_with(input: &[u8], options: ParseOptions) -> Result<Vdf<'_>> {
95 binary::parse_appinfo_with(input, options)
96}
97
98pub fn parse_packageinfo(input: &[u8]) -> Result<Vdf<'_>> {
106 binary::parse_packageinfo(input)
107}
108
109pub fn parse_packageinfo_with(input: &[u8], options: ParseOptions) -> Result<Vdf<'_>> {
111 binary::parse_packageinfo_with(input, options)
112}
113
114impl Vdf<'_> {
116 pub fn into_owned(self) -> Vdf<'static> {
121 let (key, value) = self.into_parts();
122 let owned_key: Cow<'static, str> = match key {
123 Cow::Borrowed(s) => Cow::Owned(s.to_string()),
124 Cow::Owned(s) => Cow::Owned(s),
125 };
126 Vdf::new(owned_key, value.into_owned())
127 }
128}
129
130impl Value<'_> {
131 pub fn into_owned(self) -> Value<'static> {
133 match self {
134 Value::Str(s) => Value::Str(match s {
135 Cow::Borrowed(b) => b.to_string().into(),
136 Cow::Owned(o) => o.into(),
137 }),
138 Value::Obj(obj) => Value::Obj(obj.into_owned()),
139 Value::I32(n) => Value::I32(n),
140 Value::U64(n) => Value::U64(n),
141 Value::Float(n) => Value::Float(n),
142 Value::Pointer(n) => Value::Pointer(n),
143 Value::Color(c) => Value::Color(c),
144 }
145 }
146}
147
148impl Obj<'_> {
149 pub fn into_owned(self) -> Obj<'static> {
151 let mut new = Obj::new();
152 for (k, v) in self.iter() {
153 let owned_key: Cow<'static, str> = match k {
154 Cow::Borrowed(b) => Cow::Owned(b.to_string()),
155 Cow::Owned(o) => Cow::Owned(o.clone()),
156 };
157 new.insert(owned_key, v.clone().into_owned());
159 }
160 new
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167 use alloc::vec;
168
169 const SHORTCUTS_VDF: &[u8] = &[
171 0x00, b't', b'e', b's', b't', 0x00, 0x01, b'k', b'e', b'y', 0x00, b'v', b'a', b'l', b'u', b'e', 0x00, 0x08, ];
178
179 #[test]
180 fn test_parse_binary() {
181 let vdf = parse_binary(SHORTCUTS_VDF).unwrap();
182 assert!(vdf.as_obj().is_some());
183 assert_eq!(vdf.key(), "root");
184 let obj = vdf.as_obj().unwrap();
185 let test_obj = obj.get("test").and_then(|v| v.as_obj()).unwrap();
186 assert_eq!(test_obj.get("key").and_then(|v| v.as_str()), Some("value"));
187 }
188
189 #[test]
190 fn test_parse_shortcuts() {
191 let vdf = parse_shortcuts(SHORTCUTS_VDF).unwrap();
192 assert!(vdf.as_obj().is_some());
193 assert_eq!(vdf.key(), "root");
194 let obj = vdf.as_obj().unwrap();
195 let test_obj = obj.get("test").and_then(|v| v.as_obj()).unwrap();
196 assert_eq!(test_obj.get("key").and_then(|v| v.as_str()), Some("value"));
197 }
198
199 #[test]
200 fn test_parse_appinfo() {
201 let mut input = vec![
204 0x28, 0x44, 0x56, 0x07, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
208 input.resize(76, 0);
210 let result = parse_appinfo(&input);
211 if let Err(e) = &result {
212 panic!("parse_appinfo failed: {:?}", e);
213 }
214 assert!(result.is_ok());
215 let vdf = result.unwrap();
216 assert!(vdf.key().starts_with("appinfo_universe_"));
217 }
218
219 #[test]
220 fn test_into_owned_vdf() {
221 let input = r#""root"
222 {
223 "key" "value"
224 }"#;
225 let borrowed = parse_text(input).unwrap();
226 let owned = borrowed.into_owned();
227 assert_eq!(owned.key(), "root");
228 }
229
230 #[test]
231 fn test_into_owned_value_str() {
232 let borrowed = Value::Str("test".into());
233 let owned = borrowed.into_owned();
234 assert!(matches!(owned, Value::Str(Cow::Owned(_))));
235 }
236
237 #[test]
238 fn test_into_owned_value_obj() {
239 let mut obj = Obj::new();
240 obj.insert("key", Value::Str("value".into()));
241 let borrowed = Value::Obj(obj);
242 let owned = borrowed.into_owned();
243 assert!(matches!(owned, Value::Obj(_)));
244 }
245
246 #[test]
247 fn test_into_owned_obj() {
248 let mut obj = Obj::new();
249 obj.insert("key", Value::Str("value".into()));
250 let owned = obj.into_owned();
251 assert!(owned.get("key").is_some());
252 }
253}