eon/
token_tree_from_value.rs

1//! The [`eon_syntax`] crate uses the [`TokenTree`] type as inpuit to the formatter,
2//! so in order to format a [`Value`] as we need a way to convert it to [`TokenValue`].
3//! That's the purpose of this module.
4
5use crate::{Value, value::Variant};
6
7use eon_syntax::{
8    TokenKeyValue, TokenList, TokenMap, TokenTree, TokenValue, TokenVariant, escape_and_quote,
9    is_valid_identifier,
10};
11
12impl From<Value> for TokenTree<'static> {
13    fn from(value: Value) -> Self {
14        Self::from(TokenValue::from(value))
15    }
16}
17
18impl From<Value> for TokenValue<'static> {
19    fn from(value: Value) -> Self {
20        match value {
21            Value::Null => TokenValue::Identifier("null".into()),
22            Value::Bool(true) => TokenValue::Identifier("true".into()),
23            Value::Bool(false) => TokenValue::Identifier("false".into()),
24            Value::Number(number) => TokenValue::Number(number.to_string().into()),
25            Value::String(string) => TokenValue::QuotedString(escape_and_quote(&string).into()),
26            Value::List(list) => TokenValue::List(TokenList {
27                values: list.into_iter().map(Into::into).collect(),
28                closing_comments: vec![],
29            }),
30            Value::Map(map) => {
31                let all_keys_are_identifiers = map.iter().all(|(key, _)| {
32                    if let Value::String(key) = key {
33                        is_valid_identifier(key)
34                    } else {
35                        false
36                    }
37                });
38
39                TokenValue::Map(TokenMap {
40                    key_values: map
41                        .into_iter()
42                        .map(|(key, value)| {
43                            let key = if all_keys_are_identifiers {
44                                if let Value::String(key) = key {
45                                    TokenTree::from(TokenValue::Identifier(key.into()))
46                                } else {
47                                    unreachable!();
48                                }
49                            } else {
50                                TokenTree::from(key)
51                            };
52
53                            TokenKeyValue {
54                                key,
55                                value: TokenTree::from(value),
56                            }
57                        })
58                        .collect(),
59                    closing_comments: Default::default(),
60                })
61            }
62            Value::Variant(Variant { name, values }) => TokenValue::Variant(TokenVariant {
63                name_span: None,
64                quoted_name: escape_and_quote(&name).into(),
65                values: values.into_iter().map(Into::into).collect(),
66                closing_comments: Default::default(),
67            }),
68        }
69    }
70}