Skip to main content

frozen_collections_core/emit/
collection_entry.rs

1#![expect(clippy::redundant_pub_crate, reason = "Helps clarity")]
2
3use core::fmt::{Debug, Formatter};
4use proc_macro2::TokenStream;
5use quote::{ToTokens, quote};
6use syn::{Expr, parse_quote};
7
8#[cfg(feature = "macros")]
9pub(crate) struct NonLiteralKey;
10
11/// Represents an entry in a collection used to build a frozen collection.
12pub struct CollectionEntry<K> {
13    pub(crate) key: K,
14    key_expr: Expr,
15    pub(crate) value_expr: Expr,
16}
17
18impl<K> CollectionEntry<K> {
19    /// Creates a new `CollectionEntry` for a map, using the specified key, key expression, and value expression.
20    pub const fn map_entry(key: K, key_expr: Expr, value_expr: Expr) -> Self {
21        Self { key, key_expr, value_expr }
22    }
23
24    /// Creates a new `CollectionEntry` for a set, using the specified value and value expression.
25    pub fn set_entry(value: K, value_expr: Expr) -> Self {
26        Self {
27            key: value,
28            key_expr: value_expr,
29            value_expr: parse_quote!(()),
30        }
31    }
32}
33
34impl<K> ToTokens for CollectionEntry<K> {
35    fn to_tokens(&self, tokens: &mut TokenStream) {
36        let key = &self.key_expr;
37        let value = &self.value_expr;
38        tokens.extend(quote!((#key, #value)));
39    }
40}
41
42impl<K> Clone for CollectionEntry<K>
43where
44    K: Clone,
45{
46    fn clone(&self) -> Self {
47        Self {
48            key: self.key.clone(),
49            key_expr: self.key_expr.clone(),
50            value_expr: self.value_expr.clone(),
51        }
52    }
53}
54
55impl<K> Debug for CollectionEntry<K>
56where
57    K: Debug,
58{
59    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
60        write!(
61            f,
62            "CollectionEntry {{ key: {:?}, key_expr '{}', value_expr: '{}'}}",
63            self.key,
64            self.key_expr.to_token_stream(),
65            self.value_expr.to_token_stream()
66        )
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use syn::parse_quote;
74
75    #[test]
76    fn test_map_entry() {
77        let key = "key";
78        let key_expr: Expr = parse_quote!(key);
79        let value_expr: Expr = parse_quote!(value);
80        let entry = CollectionEntry::map_entry(key, key_expr.clone(), value_expr.clone());
81
82        assert_eq!(entry.key, key);
83        assert_eq!(entry.key_expr, key_expr);
84        assert_eq!(entry.value_expr, value_expr);
85    }
86
87    #[test]
88    fn test_set_entry() {
89        let value = "value";
90        let value_expr: Expr = parse_quote!(value);
91        let entry = CollectionEntry::set_entry(value, value_expr.clone());
92
93        assert_eq!(entry.key, value);
94        assert_eq!(entry.key_expr, value_expr);
95        assert_eq!(entry.value_expr, parse_quote!(()));
96    }
97
98    #[test]
99    fn test_to_tokens() {
100        let key_expr: Expr = parse_quote!(key);
101        let value_expr: Expr = parse_quote!(value);
102        let entry = CollectionEntry::map_entry("key", key_expr, value_expr);
103        let mut tokens = TokenStream::new();
104        entry.to_tokens(&mut tokens);
105
106        assert_eq!(tokens.to_string(), "(key , value)");
107    }
108
109    #[test]
110    fn test_clone() {
111        let key = "key";
112        let key_expr: Expr = parse_quote!(key);
113        let value_expr: Expr = parse_quote!(value);
114        let entry = CollectionEntry::map_entry(key, key_expr.clone(), value_expr.clone());
115        let cloned_entry = entry.clone();
116
117        assert_eq!(cloned_entry.key, key);
118        assert_eq!(cloned_entry.key_expr, key_expr);
119        assert_eq!(cloned_entry.value_expr, value_expr);
120    }
121
122    #[test]
123    fn test_debug() {
124        let key = "key";
125        let key_expr: Expr = parse_quote!(key);
126        let value_expr: Expr = parse_quote!(value);
127        let entry = CollectionEntry::map_entry(key, key_expr, value_expr);
128        let debug_str = format!("{entry:?}");
129
130        assert_eq!(debug_str, "CollectionEntry { key: \"key\", key_expr 'key', value_expr: 'value'}");
131    }
132}