1use indexmap::IndexMap;
2use logix_vfs::LogixVfs;
3
4use crate::{
5 error::{Result, Warn},
6 parser::LogixParser,
7 token::{Brace, Token},
8 type_trait::{LogixTypeDescriptor, LogixValueDescriptor, Value},
9 types::ShortStr,
10 LogixType,
11};
12
13pub type Map<V, K = ShortStr> = IndexMap<K, V>;
14
15impl<T: LogixType, K> LogixType for Map<T, K>
16where
17 K: AsRef<str>,
18 K: From<ShortStr>,
19 K: std::hash::Hash,
20 K: Eq,
21{
22 fn descriptor() -> &'static LogixTypeDescriptor {
23 static RET: LogixTypeDescriptor = LogixTypeDescriptor {
24 name: "string",
25 doc: "a valid utf-8 string",
26 value: LogixValueDescriptor::Native,
27 };
28 &RET
29 }
30
31 fn default_value() -> Option<Self> {
32 Some(Self::new())
33 }
34
35 fn logix_parse<FS: LogixVfs>(p: &mut LogixParser<FS>) -> Result<Value<Self>> {
36 let mut map = IndexMap::new();
37
38 let start = p.req_token(
39 "map",
40 Token::Brace {
41 start: true,
42 brace: Brace::Curly,
43 },
44 )?;
45 p.req_token("map", Token::Newline(false))?;
46
47 while let Some((key, value)) = p.read_key_value("map", Brace::Curly)? {
48 if let (i, Some(_)) = map.insert_full(K::from(key.value), value.value) {
49 p.warning(Warn::DuplicateMapEntry {
50 span: key.span,
51 key: map.get_index(i).unwrap().0.as_ref().into(),
52 })?;
53 }
54 }
55
56 Ok(Value {
57 value: map,
58 span: start,
59 })
60 }
61}