Skip to main content

nitrite/collection/
document.rs

1use smallvec::SmallVec;
2use im::OrdMap;
3
4use crate::collection::nitrite_id::NitriteId;
5use crate::common::{ReadExecutor, Value, DOC_ID, DOC_MODIFIED, DOC_REVISION, DOC_SOURCE, RESERVED_FIELDS};
6use crate::errors::{ErrorKind, NitriteError, NitriteResult};
7use crate::FIELD_SEPARATOR;
8use itertools::Itertools;
9use std::borrow::Cow;
10use std::collections::{BTreeMap, BTreeSet};
11use std::fmt::{Debug, Display};
12
13type FieldVec = SmallVec<[String; 8]>;
14
15/// Represents a document in Nitrite database using lock-free persistent data structure.
16///
17/// Nitrite document are composed of key-value pairs. The key is always a
18/// [String] and value is a [Value].
19///
20/// Nitrite document supports nested documents as well. The key of a nested
21/// document is a [String] separated by the field separator (default: `.`).
22/// The field separator can be configured using [`crate::nitrite_builder::NitriteBuilder::field_separator`].
23///
24/// For example, if a document has a nested document `{"a": {"b": 1}}`, then the
25/// value inside the nested document can be retrieved by calling `document.get("a.b")`.
26///
27/// Below fields are reserved and cannot be used as key in a document.
28///
29/// * `_id` - The unique identifier of the document. If not provided, Nitrite
30/// will generate a unique [NitriteId] for the document during insertion.
31/// * `_revision` - The revision number of the document.
32/// * `_source` - The source of the document.
33/// * `_modified` - The last modified time of the document.
34///
35/// ## Lock-Free Design
36///
37/// This struct uses `im::OrdMap` (a persistent ordered map) for lock-free operation:
38/// - O(1) cloning via internal Arc sharing
39/// - Mutations create new maps via structural sharing (90% structure reused)
40/// - Each mutated document is completely independent
41/// - Zero locks, zero copy-on-write overhead
42#[derive(Clone, Eq, PartialEq, Hash, Default, Ord, PartialOrd, serde::Deserialize, serde::Serialize)]
43pub struct Document {
44    /// Persistent ordered map: O(1) clone via internal Arc, O(log n) mutations
45    data: OrdMap<String, Value>,
46}
47
48impl Document {
49    /// Creates a new empty document.
50    ///
51    /// # Examples
52    ///
53    /// ```ignore
54    /// let doc = Document::new();
55    /// assert!(doc.is_empty());
56    /// assert_eq!(doc.size(), 0);
57    /// ```
58    pub fn new() -> Self {
59        Document {
60            data: OrdMap::new(),
61        }
62    }
63
64    /// Checks if the document is empty.
65    ///
66    /// # Examples
67    ///
68    /// ```ignore
69    /// let empty_doc = Document::new();
70    /// assert!(empty_doc.is_empty());
71    ///
72    /// let mut doc = doc!{ "key": "value" };
73    /// assert!(!doc.is_empty());
74    /// ```
75    pub fn is_empty(&self) -> bool {
76        self.data.is_empty()
77    }
78
79    /// Associates the specified [Value] with the specified key in this document.
80    ///
81    /// This method inserts a key-value pair into the document. If the key already exists,
82    /// its value is updated. The method supports both top-level and embedded keys
83    /// (e.g., `"user.name"` or `"location.address.zip"`).
84    ///
85    /// # Arguments
86    ///
87    /// * `key` - The key as a string or string slice. Cannot be empty.
88    /// * `value` - The value to associate with the key. Can be any type that implements
89    ///   `Into<Value>` (primitives, strings, documents, arrays, etc.).
90    ///
91    /// # Errors
92    ///
93    /// Returns an error if:
94    /// * The key is empty
95    /// * The key contains the reserved field `_id` with a non-NitriteId value
96    ///
97    /// # Examples
98    ///
99    /// Basic insertion:
100    /// ```ignore
101    /// let mut doc = Document::new();
102    /// doc.put("name", "Alice")?;
103    /// doc.put("age", 30)?;
104    /// assert_eq!(doc.size(), 2);
105    /// ```
106    ///
107    /// Nested document insertion:
108    /// ```ignore
109    /// let mut doc = Document::new();
110    /// doc.put("user.name", "Alice")?;
111    /// doc.put("user.email", "alice@example.com")?;
112    /// assert_eq!(doc.get("user.name")?, Value::String("Alice".to_string()));
113    /// ```
114    ///
115    /// Updating existing key:
116    /// ```ignore
117    /// let mut doc = doc!{ "status": "inactive" };
118    /// doc.put("status", "active")?;
119    /// assert_eq!(doc.get("status")?, Value::String("active".to_string()));
120    /// ```
121    pub fn put<'a, T: Into<Value>>(&mut self, key: impl Into<Cow<'a, str>>, value: T) -> NitriteResult<()> {
122        let key = key.into();
123        // key cannot be empty
124        if key.is_empty() {
125            log::error!("Document does not support empty key");
126            return Err(NitriteError::new(
127                "Document does not support empty key",
128                ErrorKind::InvalidOperation,
129            ));
130        }
131        
132        let value = value.into();
133
134        // validate the _id field
135        if key == DOC_ID && !value.is_nitrite_id() {
136            log::error!("Document id is an auto generated field and cannot be set manually");
137            return Err(NitriteError::new(
138                "Document id is an auto generated field and cannot be set manually",
139                ErrorKind::InvalidOperation,
140            ));
141        }
142
143        // if field name contains field separator, split the fields, and put the value
144        // accordingly associated with the embedded field.
145        if FIELD_SEPARATOR.read_with(|sep| key.contains(sep)) {
146            let splits: Vec<&str> = FIELD_SEPARATOR.read_with(|it| key.split(it).collect());
147            self.deep_put(&splits, value)
148        } else {
149            self.data = self.data.update(key.to_string(), value);
150            Ok(())
151        }
152    }
153
154    /// Returns the [Value] to which the specified key is associated, or [Value::Null]
155    /// if this document contains no mapping for the key.
156    ///
157    /// This method retrieves the value associated with a key. If the key does not exist,
158    /// it returns [Value::Null]. The method supports both top-level and embedded keys
159    /// (e.g., `"location.address.zip"`).
160    ///
161    /// # Arguments
162    ///
163    /// * `key` - The key to look up as a string slice.
164    ///
165    /// # Returns
166    ///
167    /// Returns the associated [Value], or [Value::Null] if the key does not exist.
168    ///
169    /// # Examples
170    ///
171    /// Retrieving a top-level key:
172    /// ```ignore
173    /// let doc = doc!{ "name": "Alice", "age": 30 };
174    /// assert_eq!(doc.get("name")?, Value::String("Alice".to_string()));
175    /// assert_eq!(doc.get("age")?, Value::I32(30));
176    /// ```
177    ///
178    /// Accessing nested documents:
179    /// ```ignore
180    /// let doc = doc!{
181    ///     "location": {
182    ///         "city": "New York",
183    ///         "zip": 10001
184    ///     }
185    /// };
186    /// assert_eq!(doc.get("location.city")?, Value::String("New York".to_string()));
187    /// assert_eq!(doc.get("location.zip")?, Value::I32(10001));
188    /// ```
189    ///
190    /// Accessing array elements:
191    /// ```ignore
192    /// let doc = doc!{ "items": [1, 2, 3] };
193    /// assert_eq!(doc.get("items.0")?, Value::I32(1));
194    /// assert_eq!(doc.get("items.1")?, Value::I32(2));
195    /// ```
196    ///
197    /// Non-existent key returns Null:
198    /// ```ignore
199    /// let doc = doc!{ "name": "Alice" };
200    /// assert_eq!(doc.get("missing")?, Value::Null);
201    /// ```
202    pub fn get(&self, key: &str) -> NitriteResult<Value> {
203        match self.data.get(key) {
204            Some(value) => Ok(value.clone()),
205            None => {
206                // Only check for embedded key if not found at top level
207                if FIELD_SEPARATOR.read_with(|sep| key.contains(sep)) {
208                    self.deep_get(key)
209                } else {
210                    Ok(Value::Null)
211                }
212            }
213        }
214    }
215
216    /// Return the [NitriteId] associated with this document.
217    ///
218    /// If the document does not have an `_id` field, this method automatically generates
219    /// a new [NitriteId] and assigns it to the document. This method mutates the document
220    /// only if an ID needs to be generated.
221    ///
222    /// # Returns
223    ///
224    /// The [NitriteId] associated with this document.
225    ///
226    /// # Examples
227    ///
228    /// Getting the ID of an existing document:
229    /// ```ignore
230    /// let mut doc = doc!{ "name": "Alice" };
231    /// let id = doc.id()?;
232    /// assert!(!id.to_string().is_empty());
233    /// // After calling id(), the document now has an _id field
234    /// assert!(doc.has_id());
235    /// ```
236    ///
237    /// Auto-generating ID when missing:
238    /// ```ignore
239    /// let mut doc1 = doc!{ "name": "Alice" };
240    /// let mut doc2 = doc!{ "name": "Bob" };
241    ///
242    /// let id1 = doc1.id()?;
243    /// let id2 = doc2.id()?;
244    ///
245    /// // Each document gets a unique ID
246    /// assert_ne!(id1, id2);
247    /// ```
248    pub fn id(&mut self) -> NitriteResult<NitriteId> {
249        if let Some(Value::NitriteId(id)) = self.data.get(DOC_ID) {
250            Ok(*id)
251        } else {
252            // if _id field is not populated already, create a new id
253            // and set it in the document
254            let nitrite_id = NitriteId::new();
255            self.data = self.data.update(
256                DOC_ID.to_string(),
257                Value::NitriteId(nitrite_id),
258            );
259            Ok(nitrite_id)
260        }
261    }
262
263    /// Retrieves all fields (top level and embedded) associated with this document.
264    ///
265    /// This method returns a collection of all field paths in the document, including
266    /// top-level fields and embedded fields from nested documents. Embedded fields are
267    /// represented using the field separator (default: `.`). Reserved fields
268    /// (`_id`, `_revision`, `_source`, `_modified`) are excluded from the result.
269    ///
270    /// # Returns
271    ///
272    /// A [FieldVec] containing all field paths in the document.
273    ///
274    /// # Examples
275    ///
276    /// Retrieving fields from a simple document:
277    /// ```ignore
278    /// let doc = doc!{ "name": "Alice", "age": 30 };
279    /// let fields = doc.fields();
280    /// assert_eq!(fields.len(), 2);
281    /// assert!(fields.contains(&"name".to_string()));
282    /// assert!(fields.contains(&"age".to_string()));
283    /// ```
284    ///
285    /// Retrieving fields from a nested document:
286    /// ```ignore
287    /// let doc = doc!{
288    ///     "user": {
289    ///         "name": "Alice",
290    ///         "email": "alice@example.com"
291    ///     },
292    ///     "status": "active"
293    /// };
294    /// let fields = doc.fields();
295    /// // Returns ["user.name", "user.email", "status"]
296    /// assert!(fields.contains(&"user.name".to_string()));
297    /// assert!(fields.contains(&"user.email".to_string()));
298    /// assert!(fields.contains(&"status".to_string()));
299    /// ```
300    ///
301    /// Empty document:
302    /// ```ignore
303    /// let doc = Document::new();
304    /// let fields = doc.fields();
305    /// assert!(fields.is_empty());
306    /// ```
307    pub fn fields(&self) -> FieldVec {
308        self.get_fields_internal("")
309    }
310
311    /// Checks if this document has a nitrite id.
312    ///
313    /// # Returns
314    ///
315    /// `true` if the document has an `_id` field, `false` otherwise.
316    ///
317    /// # Examples
318    ///
319    /// Checking ID presence:
320    /// ```ignore
321    /// let mut doc = doc!{ "name": "Alice" };
322    /// assert!(!doc.has_id());  // No ID yet
323    ///
324    /// let _id = doc.id()?;      // Generate ID
325    /// assert!(doc.has_id());    // Now has ID
326    /// ```
327    pub fn has_id(&self) -> bool {
328        self.data.contains_key(DOC_ID)
329    }
330
331    /// Removes the key and its value from the document.
332    ///
333    /// Deletes the key-value pair associated with the given key. If the key does not exist,
334    /// the operation succeeds without error. The method supports both top-level and embedded keys.
335    ///
336    /// # Arguments
337    ///
338    /// * `key` - The key to remove as a string slice.
339    ///
340    /// # Errors
341    ///
342    /// Returns an error if the key contains invalid embedded field separators.
343    ///
344    /// # Examples
345    ///
346    /// Removing a top-level key:
347    /// ```ignore
348    /// let mut doc = doc!{ "name": "Alice", "age": 30 };
349    /// doc.remove("age")?;
350    /// assert_eq!(doc.get("age")?, Value::Null);
351    /// assert_eq!(doc.size(), 1);
352    /// ```
353    ///
354    /// Removing a nested field:
355    /// ```ignore
356    /// let mut doc = doc!{
357    ///     "user": {
358    ///         "name": "Alice",
359    ///         "email": "alice@example.com"
360    ///     }
361    /// };
362    /// doc.remove("user.email")?;
363    /// assert_eq!(doc.get("user.email")?, Value::Null);
364    /// assert_eq!(doc.get("user.name")?, Value::String("Alice".to_string()));
365    /// ```
366    ///
367    /// Removing non-existent key succeeds:
368    /// ```ignore
369    /// let mut doc = doc!{ "name": "Alice" };
370    /// doc.remove("missing")?;  // No error
371    /// assert_eq!(doc.size(), 1);
372    /// ```
373    pub fn remove(&mut self, key: &str) -> NitriteResult<()> {
374        if FIELD_SEPARATOR.read_with(|sep| key.contains(sep)) {
375            // if the field is an embedded field,
376            // run a deep scan and remove the last field
377            let splits: Vec<&str> = FIELD_SEPARATOR.read_with(|it| key.split(it).collect());
378            self.deep_remove(&splits)
379        } else {
380            self.data = self.data.without(key);
381            Ok(())
382        }
383    }
384
385    /// Returns the number of entries in the document.
386    ///
387    /// # Returns
388    ///
389    /// The count of key-value pairs in this document (top-level only, not including nested entries).
390    ///
391    /// # Examples
392    ///
393    /// Counting entries:
394    /// ```ignore
395    /// let doc = Document::new();
396    /// assert_eq!(doc.size(), 0);
397    ///
398    /// let doc = doc!{ "name": "Alice", "age": 30 };
399    /// assert_eq!(doc.size(), 2);
400    ///
401    /// // Nested documents count as one entry
402    /// let doc = doc!{ "user": { "name": "Alice" }, "status": "active" };
403    /// assert_eq!(doc.size(), 2);
404    /// ```
405    pub fn size(&self) -> usize {
406        self.data.len()
407    }
408
409    /// Merges a document in this document.
410    ///
411    /// Merges all key-value pairs from another document into this one. If a key already exists:
412    /// - If both values are documents, they are merged recursively
413    /// - Otherwise, the value from `other` overwrites the existing value
414    ///
415    /// # Arguments
416    ///
417    /// * `other` - The document to merge into this one.
418    ///
419    /// # Examples
420    ///
421    /// Basic merge:
422    /// ```ignore
423    /// let mut doc1 = doc!{ "name": "Alice", "age": 30 };
424    /// let doc2 = doc!{ "email": "alice@example.com", "age": 31 };
425    /// doc1.merge(&doc2)?;
426    ///
427    /// assert_eq!(doc1.get("name")?, Value::String("Alice".to_string()));
428    /// assert_eq!(doc1.get("age")?, Value::I32(31));       // Overwritten
429    /// assert_eq!(doc1.get("email")?, Value::String("alice@example.com".to_string()));
430    /// ```
431    ///
432    /// Recursive merge of nested documents:
433    /// ```ignore
434    /// let mut doc1 = doc!{
435    ///     "user": {
436    ///         "name": "Alice",
437    ///         "age": 30
438    ///     }
439    /// };
440    /// let doc2 = doc!{
441    ///     "user": {
442    ///         "email": "alice@example.com"
443    ///     }
444    /// };
445    /// doc1.merge(&doc2)?;
446    ///
447    /// assert_eq!(doc1.get("user.name")?, Value::String("Alice".to_string()));
448    /// assert_eq!(doc1.get("user.age")?, Value::I32(30));
449    /// assert_eq!(doc1.get("user.email")?, Value::String("alice@example.com".to_string()));
450    /// ```
451    pub fn merge(&mut self, other: &Document) -> NitriteResult<()> {
452        for (key, value) in other.data.iter() {
453            match value {
454                Value::Document(obj) => {
455                    // if the value is a document, merge it recursively
456                    if let Some(Value::Document(mut nested_obj)) = self.data.get(key).cloned() {
457                        nested_obj.merge(obj)?;
458                        self.data = self.data.update(key.clone(), Value::Document(nested_obj));
459                    } else {
460                        // Otherwise, just set the value
461                        self.data = self.data.update(key.clone(), value.clone());
462                    }
463                }
464                _ => {
465                    // if there is no embedded document, put the field in the document
466                    self.data = self.data.update(key.clone(), value.clone());
467                }
468            }
469        }
470        Ok(())
471    }
472
473    /// Checks if a top level key exists in the document.
474    ///
475    /// This method only checks for top-level keys, not embedded fields. Use [contains_field]
476    /// to check for embedded fields.
477    ///
478    /// # Arguments
479    ///
480    /// * `key` - The key to check as a string slice.
481    ///
482    /// # Returns
483    ///
484    /// `true` if the key exists at the top level, `false` otherwise.
485    ///
486    /// # Examples
487    ///
488    /// Checking top-level keys:
489    /// ```ignore
490    /// let doc = doc!{
491    ///     "name": "Alice",
492    ///     "user": { "email": "alice@example.com" }
493    /// };
494    ///
495    /// assert!(doc.contains_key("name"));
496    /// assert!(doc.contains_key("user"));
497    /// assert!(!doc.contains_key("email"));  // email is nested, not top-level
498    /// assert!(!doc.contains_key("age"));    // doesn't exist
499    /// ```
500    pub fn contains_key(&self, key: &str) -> bool {
501        self.data.contains_key(key)
502    }
503
504    /// Checks if a top level field or embedded field exists in the document.
505    ///
506    /// This method checks both top-level and embedded fields. It returns `true` if the
507    /// field exists at any level in the document hierarchy.
508    ///
509    /// # Arguments
510    ///
511    /// * `field` - The field path to check as a string slice (e.g., `"user.email"`).
512    ///
513    /// # Returns
514    ///
515    /// `true` if the field exists at any level, `false` otherwise.
516    ///
517    /// # Examples
518    ///
519    /// Checking embedded fields:
520    /// ```ignore
521    /// let doc = doc!{
522    ///     "name": "Alice",
523    ///     "location": {
524    ///         "city": "New York",
525    ///         "address": {
526    ///             "zip": 10001
527    ///         }
528    ///     }
529    /// };
530    ///
531    /// assert!(doc.contains_field("name"));                     // Top-level
532    /// assert!(doc.contains_field("location"));                 // Top-level document
533    /// assert!(doc.contains_field("location.city"));            // Nested
534    /// assert!(doc.contains_field("location.address.zip"));     // Deeply nested
535    /// assert!(!doc.contains_field("location.country"));        // Doesn't exist
536    /// ```
537    pub fn contains_field(&self, field: &str) -> bool {
538        if self.contains_key(field) {
539            true
540        } else {
541            self.fields().contains(&field.to_string())
542        }
543    }
544
545    /// Gets the document revision number.
546    ///
547    /// The revision number is an internal metadata field that tracks how many times
548    /// the document has been modified. Returns 0 if the document has not been stored
549    /// in a collection yet.
550    ///
551    /// # Returns
552    ///
553    /// The revision number as an `i32`, or 0 if not set.
554    ///
555    /// # Examples
556    ///
557    /// ```ignore
558    /// let doc = Document::new();
559    /// assert_eq!(doc.revision()?, 0);
560    ///
561    /// // After inserting and updating in a collection, revision increments
562    /// let doc_from_collection = collection.find(all())?.next()?;
563    /// let revision = doc_from_collection.revision()?;
564    /// // revision will be > 0 depending on update history
565    /// ```
566    pub fn revision(&self) -> NitriteResult<i32> {
567        if let Ok(Value::I32(revision)) = self.get(DOC_REVISION) {
568            Ok(revision)
569        } else {
570            Ok(0)
571        }
572    }
573
574    /// Gets the source of this document.
575    ///
576    /// The source is a metadata field that indicates where the document came from
577    /// or what operation created it. Returns an empty string if not set.
578    ///
579    /// # Returns
580    ///
581    /// The source as a [String], or an empty string if not set.
582    ///
583    /// # Examples
584    ///
585    /// ```ignore
586    /// let doc = Document::new();
587    /// assert_eq!(doc.source()?, "");
588    ///
589    /// // Documents from collections may have source set by the database
590    /// ```
591    pub fn source(&self) -> NitriteResult<String> {
592        if let Ok(Value::String(source)) = self.get(DOC_SOURCE) {
593            Ok(source.clone())
594        } else {
595            Ok("".to_string())
596        }
597    }
598
599    /// Gets last modified time of this document since epoch.
600    ///
601    /// Returns the timestamp (in milliseconds since Unix epoch) when the document
602    /// was last modified. Returns 0 if the document has not been stored in a collection yet.
603    ///
604    /// # Returns
605    ///
606    /// The last modified time as an `i64` (milliseconds since epoch), or 0 if not set.
607    ///
608    /// # Examples
609    ///
610    /// ```ignore
611    /// let doc = Document::new();
612    /// assert_eq!(doc.last_modified_since_epoch()?, 0);
613    ///
614    /// // After inserting in a collection, timestamp is set
615    /// let doc_from_collection = collection.find(all())?.next()?;
616    /// let timestamp = doc_from_collection.last_modified_since_epoch()?;
617    /// assert!(timestamp > 0);
618    /// ```
619    pub fn last_modified_since_epoch(&self) -> NitriteResult<i64> {
620        if let Ok(Value::I64(modified)) = self.get(DOC_MODIFIED) {
621            Ok(modified)
622        } else {
623            Ok(0)
624        }
625    }
626
627    /// Converts this document to a [BTreeMap].
628    ///
629    /// Creates a new [BTreeMap] containing all the key-value pairs from this document.
630    /// This is useful for interoperability with code expecting a standard map type.
631    ///
632    /// # Returns
633    ///
634    /// A new [BTreeMap] containing all entries from this document.
635    ///
636    /// # Examples
637    ///
638    /// ```ignore
639    /// let doc = doc!{ "name": "Alice", "age": 30 };
640    /// let map = doc.to_map();
641    /// assert_eq!(map.len(), 2);
642    /// assert_eq!(map.get("name").unwrap(), &Value::String("Alice".to_string()));
643    /// ```
644    pub fn to_map(&self) -> BTreeMap<String, Value> {
645        self.data.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
646    }
647
648    /// Gets an iterator over the key-value pairs of this document.
649    ///
650    /// Returns a [DocumentIter] that iterates over all top-level key-value pairs
651    /// in the document. Each iteration yields a tuple of (key, value) where both
652    /// are owned values.
653    ///
654    /// # Returns
655    ///
656    /// A [DocumentIter] for iterating over the document entries.
657    ///
658    /// # Examples
659    ///
660    /// Iterating over document entries:
661    /// ```ignore
662    /// let doc = doc!{ "name": "Alice", "age": 30 };
663    /// let mut count = 0;
664    /// for (key, value) in doc.iter() {
665    ///     count += 1;
666    ///     println!("{}: {}", key, value);
667    /// }
668    /// assert_eq!(count, 2);
669    /// ```
670    ///
671    /// Collecting entries into a vector:
672    /// ```ignore
673    /// let doc = doc!{ "name": "Alice", "age": 30 };
674    /// let entries: Vec<_> = doc.iter().collect();
675    /// assert_eq!(entries.len(), 2);
676    /// ```
677    pub fn iter(&self) -> DocumentIter {
678        DocumentIter {
679            keys: self.data.keys().cloned().collect(),
680            data: self.clone(),
681            index: 0,
682        }
683    }
684
685    pub(crate) fn to_pretty_json(&self, indent: usize) -> String {
686        if self.data.is_empty() {
687            return "{}".to_string();
688        }
689
690        let estimated_size = self.data.len() * 30 + indent * 2;
691        let mut json_string = String::with_capacity(estimated_size);
692
693        json_string.push_str("{\n");
694        let indent_str = " ".repeat(indent + 2);
695        for (key, value) in self.data.iter() {
696            json_string.push_str(&format!(
697                "{}\"{}\": {},\n",
698                indent_str,
699                key,
700                value.to_pretty_json(indent + 2)
701            ));
702        }
703
704        json_string.pop();
705        json_string.pop();
706        json_string.push_str(&format!("\n{}}}", " ".repeat(indent)));
707        json_string
708    }
709
710    pub(crate) fn to_debug_string(&self, indent: usize) -> String {
711        if self.data.is_empty() {
712            return "{}".to_string();
713        }
714
715        let mut debug_string = String::new();
716        debug_string.push_str("{\n");
717        let indent_str = " ".repeat(indent + 2);
718        for (key, value) in self.data.iter() {
719            debug_string.push_str(&format!(
720                "{}\"{}\": {},\n",
721                indent_str,
722                key,
723                value.to_debug_string(indent + 2)
724            ));
725        }
726
727        debug_string.pop();
728        debug_string.pop();
729        debug_string.push_str(&format!("\n{}}}", " ".repeat(indent)));
730        debug_string
731    }
732
733    fn is_embedded(&self, key: &str) -> bool {
734        FIELD_SEPARATOR.read_with(|it| key.contains(it))
735    }
736
737    fn get_fields_internal(&self, prefix: &str) -> FieldVec {
738        let mut fields = FieldVec::new();
739        let separator = FIELD_SEPARATOR.read_with(|s| s.clone());
740
741        // iterate top level keys
742        for key in self.data.keys() {
743            // ignore the reserved fields
744            if RESERVED_FIELDS.contains(&key.as_str()) {
745                continue;
746            }
747
748            if key.is_empty() {
749                continue;
750            }
751
752            let field = if prefix.is_empty() {
753                // level-1 fields
754                key.clone()
755            } else {
756                // level-n fields, separated by field separator
757                format!("{}{}{}", prefix, separator, key)
758            };
759
760            if let Some(Value::Document(doc)) = self.data.get(key) {
761                // if the value is a document, traverse its fields recursively,
762                // prefix would be the field name of the document
763                fields.append(&mut doc.get_fields_internal(&field));
764            } else {
765                // if there is no more embedded document, add the field to the list
766                fields.push(field);
767            }
768        }
769        fields
770    }
771
772    fn deep_get(&self, key: &str) -> NitriteResult<Value> {
773        if !self.is_embedded(key) {
774            Ok(Value::Null)
775        } else {
776            self.get_by_embedded_key(key)
777        }
778    }
779
780    fn deep_put(&mut self, splits: &[&str], value: Value) -> NitriteResult<()> {
781        if splits.is_empty() {
782            log::error!("Empty embedded key");
783            return Err(NitriteError::new(
784                "Empty embedded key",
785                ErrorKind::ValidationError,
786            ));
787        }
788
789        let key = splits[0];
790        if key.is_empty() {
791            log::error!("Document does not support empty key");
792            return Err(NitriteError::new(
793                "Document does not support empty key",
794                ErrorKind::InvalidOperation,
795            ));
796        }
797
798        if splits.len() == 1 {
799            // if last key, simply put in the current document
800            self.put(key, value)
801        } else {
802            let remaining_splits = &splits[1..];
803            if let Some(Value::Document(mut obj)) = self.data.get(key).cloned() {
804                // if the current level value is embedded doc, scan to the next level
805                let result = obj.deep_put(remaining_splits, value);
806                self.data = self.data.update(key.to_string(), Value::Document(obj));
807                result
808            } else {
809                // if current level value is null, create a new document
810                let mut nested_doc = Document::new();
811                let result = nested_doc.deep_put(remaining_splits, value);
812                self.data = self.data.update(key.to_string(), Value::Document(nested_doc));
813                result
814            }
815        }
816    }
817
818    fn deep_remove(&mut self, splits: &[&str]) -> NitriteResult<()> {
819        if splits.is_empty() {
820            log::error!("Empty embedded key");
821            return Err(NitriteError::new(
822                "Empty embedded key",
823                ErrorKind::ValidationError,
824            ));
825        }
826
827        let key = splits[0];
828        if key.is_empty() {
829            log::error!("Document does not support empty key");
830            return Err(NitriteError::new(
831                "Document does not support empty key",
832                ErrorKind::InvalidOperation,
833            ));
834        }
835
836        if splits.len() == 1 {
837            // if last key, simply remove from the current document
838            self.remove(key)
839        } else {
840            let remaining_splits = &splits[1..];
841
842            match self.data.get(key) {
843                Some(Value::Document(obj)) => {
844                    // if the current level value is embedded doc, scan to the next level
845                    let mut nested_doc = obj.clone();
846                    let result = nested_doc.deep_remove(remaining_splits);
847                    if nested_doc.is_empty() {
848                        // if the next level document is an empty one
849                        // remove the current level document also
850                        self.data = self.data.without(key);
851                    } else {
852                        self.data = self.data.update(key.to_string(), Value::Document(nested_doc));
853                    }
854                    result
855                }
856                Some(Value::Array(arr)) => {
857                    let first = splits[1];
858                    // if the current level value is an iterable,
859                    // remove the element at the next level
860                    if let Ok(index) = first.parse::<isize>() {
861                        if index < 0 {
862                            log::error!(
863                                "Invalid array index {} to access array inside a document",
864                                &index
865                            );
866                            return Err(NitriteError::new(
867                                &format!(
868                                    "Invalid array index {} to access array inside a document",
869                                    &index
870                                ),
871                                ErrorKind::ValidationError,
872                            ));
873                        }
874
875                        let index = index as usize;
876                        if index >= arr.len() {
877                            log::error!("Array index {} out of bound", &index);
878                            return Err(NitriteError::new(
879                                &format!("Array index {} out of bound", &index),
880                                ErrorKind::ValidationError,
881                            ));
882                        }
883
884                        let item = &arr[index];
885                        if let (Value::Document(obj), true) = (item, splits.len() > 2) {
886                            // if there are more splits, then this is an embedded document
887                            let mut nested_doc = obj.clone();
888                            let result = nested_doc.deep_remove(&remaining_splits[1..]);
889                            if nested_doc.is_empty() {
890                                // if the next level document is an empty one
891                                // remove the element from array
892                                let mut new_arr = arr.clone();
893                                new_arr.remove(index);
894                                self.data = self.data.update(key.to_string(), Value::Array(new_arr));
895                            } else {
896                                let mut new_arr = arr.clone();
897                                new_arr[index] = Value::Document(nested_doc);
898                                self.data = self.data.update(key.to_string(), Value::Array(new_arr));
899                            }
900                            result
901                        } else {
902                            // if there are no more splits, remove the element at the next level
903                            let mut new_arr = arr.clone();
904                            new_arr.remove(index);
905                            self.data = self.data.update(key.to_string(), Value::Array(new_arr));
906                            Ok(())
907                        }
908                    } else {
909                        log::error!(
910                            "Invalid array index {} to access array inside a document",
911                            first
912                        );
913                        Err(NitriteError::new(
914                            &format!(
915                                "Invalid array index {} to access array inside a document",
916                                first
917                            ),
918                            ErrorKind::ValidationError,
919                        ))
920                    }
921                }
922                _ => {
923                    // if current level value is null, remove the key
924                    self.data = self.data.without(key);
925                    Ok(())
926                }
927            }
928        }
929    }
930
931    fn get_by_embedded_key(&self, key: &str) -> NitriteResult<Value> {
932        let separator = FIELD_SEPARATOR.read_with(|s| s.clone());
933        let splits: Vec<&str> = key.split(&separator).collect();
934        
935        if splits.is_empty() {
936            return Ok(Value::Null);
937        }
938
939        let first = splits[0];
940        if first.is_empty() {
941            log::error!("Document does not support empty key");
942            return Err(NitriteError::new(
943                "Document does not support empty key",
944                ErrorKind::InvalidOperation,
945            ));
946        }
947
948        // get current level value and scan to next level using remaining keys
949        self.recursive_get(self.data.get(first), &splits[1..])
950    }
951
952    fn recursive_get(&self, value: Option<&Value>, splits: &[&str]) -> NitriteResult<Value> {
953        let value = match value {
954            None => return Ok(Value::Null),
955            Some(v) => v,
956        };
957
958        if splits.is_empty() {
959            return Ok(value.clone());
960        }
961
962        let key = splits[0];
963        if key.is_empty() {
964            log::error!("Document does not support empty key");
965            return Err(NitriteError::new(
966                "Document does not support empty key",
967                ErrorKind::InvalidOperation,
968            ));
969        }
970
971        match value {
972            Value::Document(obj) => {
973                // if the current level value is document, scan to the next level with remaining keys
974                self.recursive_get(obj.data.get(key), &splits[1..])
975            }
976            Value::Array(arr) => {
977                // if the current level value is an iterable
978                let first = key;
979                if let Ok(index) = first.parse::<isize>() {
980                    // check index lower bound
981                    if index < 0 {
982                        log::error!(
983                            "Invalid array index {} to access array inside a document",
984                            &index
985                        );
986                        return Err(NitriteError::new(
987                            &format!(
988                                "Invalid array index {} to access array inside a document",
989                                &index
990                            ),
991                            ErrorKind::ValidationError,
992                        ));
993                    }
994
995                    // check index upper bound
996                    let index = index as usize;
997                    if index >= arr.len() {
998                        log::error!("Array index {} out of bound", &index);
999                        return Err(NitriteError::new(
1000                            &format!("Array index {} out of bound", &index),
1001                            ErrorKind::ValidationError,
1002                        ));
1003                    }
1004
1005                    // get the value at the index from the list
1006                    let item = &arr[index];
1007                    self.recursive_get(Some(item), &splits[1..])
1008                } else {
1009                    // if the current key is not an integer, decompose the list
1010                    self.decompose(arr, splits)
1011                }
1012            }
1013            _ => Ok(Value::Null), // if no match found return null
1014        }
1015    }
1016
1017    fn decompose(&self, arr: &[Value], splits: &[&str]) -> NitriteResult<Value> {
1018        let mut items: Vec<Value> = Vec::with_capacity(arr.len());
1019
1020        for item in arr {
1021            // scan the item using remaining keys and use ? for error propagation
1022            let result = self.recursive_get(Some(item), splits)?;
1023
1024            match result {
1025                Value::Array(arr) => {
1026                    // if the result is an iterable, add all items to the list
1027                    for v in arr {
1028                        items.push(v);
1029                    }
1030                }
1031                value => {
1032                    // if the result is not an iterable, add the result to the list
1033                    items.push(value);
1034                }
1035            }
1036        }
1037        // remove duplicates from the list
1038        Ok(Value::Array(items.iter().unique().cloned().collect::<Vec<_>>()))
1039    }
1040}
1041
1042impl Debug for Document {
1043    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1044        write!(f, "{}", self.to_debug_string(0))
1045    }
1046}
1047
1048impl Display for Document {
1049    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1050        write!(f, "{}", self.to_pretty_json(0))
1051    }
1052}
1053
1054pub struct DocumentIter {
1055    keys: Vec<String>,
1056    data: Document,
1057    index: usize,
1058}
1059
1060impl Iterator for DocumentIter {
1061    type Item = (String, Value);
1062
1063    fn next(&mut self) -> Option<Self::Item> {
1064        if self.index < self.keys.len() {
1065            let key = &self.keys[self.index];
1066            if let Some(value) = self.data.data.get(key) {
1067                let result = (key.clone(), value.clone());
1068                self.index += 1;
1069                return Some(result);
1070            }
1071            self.index += 1;
1072            self.next()
1073        } else {
1074            None
1075        }
1076    }
1077
1078    fn size_hint(&self) -> (usize, Option<usize>) {
1079        let remaining = self.keys.len().saturating_sub(self.index);
1080        (remaining, Some(remaining))
1081    }
1082}
1083
1084pub fn normalize(value: &str) -> String {
1085    value.trim_matches('"').to_string()
1086}
1087
1088/// Creates a Nitrite Document with JSON-like syntax.
1089///
1090/// # Examples
1091///
1092/// ```rust
1093/// use nitrite::doc;
1094///
1095/// // Empty document
1096/// let empty = doc!{};
1097///
1098/// // Simple key-value pairs
1099/// let simple = doc!{
1100///     name: "Alice",
1101///     age: 30
1102/// };
1103///
1104/// // With expressions
1105/// let base = 100;
1106/// let with_expr = doc!{
1107///     name: "Bob",
1108///     score: (base * 2),
1109///     computed: (base + 50)
1110/// };
1111///
1112/// // Nested documents and arrays
1113/// let complex = doc!{
1114///     user: {
1115///         name: "Charlie",
1116///         tags: ["admin", "user"]
1117///     },
1118///     values: [1, 2, 3]
1119/// };
1120/// ```
1121#[macro_export]
1122macro_rules! doc {
1123    // match an empty document (with braces for backward compat)
1124    ({}) => {
1125        $crate::collection::Document::new()
1126    };
1127
1128    // match an empty document (new syntax)
1129    () => {
1130        $crate::collection::Document::new()
1131    };
1132
1133    // match a document with key value pairs (old syntax with outer braces - for backward compat)
1134    ({ $($key:tt : $value:tt),* $(,)? }) => {
1135        $crate::doc!($($key : $value),*)
1136    };
1137
1138    // match a document with key value pairs (new syntax without outer braces)
1139    ($($key:tt : $value:tt),* $(,)?) => {
1140        {
1141            #[allow(unused_imports)]
1142            use $crate::doc_value;
1143
1144            let mut doc = $crate::collection::Document::new();
1145            $(
1146                doc.put(&$crate::collection::normalize(stringify!($key)), $crate::doc_value!($value))
1147                .expect(&format!("Failed to put value {} in document", stringify!($value)));
1148            )*
1149            doc
1150        }
1151    };
1152}
1153
1154/// Helper macro to convert values for the doc! macro.
1155/// Handles nested documents, arrays, and expressions.
1156#[macro_export]
1157macro_rules! doc_value {
1158    // match a nested document
1159    ({ $($key:tt : $value:tt),* $(,)? }) => {
1160        {
1161            $crate::common::Value::Document($crate::doc!{ $($key : $value),* })
1162        }
1163    };
1164
1165    // match an array of values
1166    ([ $($value:tt),* $(,)? ]) => {
1167        $crate::common::Value::Array(vec![$($crate::doc_value!($value)),*])
1168    };
1169
1170    // match an expression (variable, function call, arithmetic in parens, literals, etc.)
1171    ($value:expr) => {
1172        $crate::common::Value::from($value)
1173    };
1174}
1175
1176#[cfg(test)]
1177mod tests {
1178    use std::string;
1179
1180    use super::*;
1181    use crate::collection::Document;
1182    use crate::common::Value::Null;
1183    use crate::{create_document, document_from_map, empty_document};
1184
1185    fn set_up() -> Document {
1186        doc!{
1187            score: 1034,
1188            location: {
1189                state: "NY",
1190                city: "New York",
1191                address: {
1192                    line1: "40",
1193                    line2: "ABC Street",
1194                    house: ["1", "2", "3"],
1195                    zip: 10001,
1196                },
1197            },
1198            category: ["food", "produce", "grocery"],
1199            obj_array: [
1200                {
1201                    value: 1,
1202                },
1203                {
1204                    value: 2,
1205                },
1206            ]
1207        }
1208    }
1209
1210    #[test]
1211    fn test_normalize() {
1212        let value = "\"ABC\"".to_string();
1213        let result = normalize(&value);
1214        assert_eq!(result, "ABC");
1215
1216        let value = "ABC".to_string();
1217        let result = normalize(&value);
1218        assert_eq!(result, "ABC");
1219    }
1220
1221    #[test]
1222    fn test_empty_document() {
1223        let doc = empty_document();
1224        assert!(doc.is_empty());
1225    }
1226
1227    #[test]
1228    fn test_new() {
1229        let doc = Document::new();
1230        assert!(doc.is_empty());
1231    }
1232
1233    #[test]
1234    fn test_document_from_map() {
1235        let mut map = BTreeMap::new();
1236        map.insert("key1".to_string(), Value::I32(1));
1237        map.insert("key2".to_string(), Value::String("value".to_string()));
1238        map.insert(
1239            "key3".to_string(),
1240            Value::Array(vec![Value::I32(1), Value::I32(2)]),
1241        );
1242        map.insert("key4".to_string(), Value::Document(Document::new()));
1243
1244        let doc = document_from_map(&map).unwrap();
1245        assert_eq!(doc.size(), 4);
1246    }
1247
1248    #[test]
1249    fn test_create_document() {
1250        let doc = create_document("key", Value::I32(1)).unwrap();
1251        assert_eq!(doc.size(), 1);
1252    }
1253
1254    #[test]
1255    fn test_is_empty() {
1256        let doc = empty_document();
1257        assert!(doc.is_empty());
1258
1259        let doc = set_up();
1260        assert!(!doc.is_empty());
1261    }
1262
1263    #[test]
1264    fn test_get() {
1265        let doc = set_up();
1266        let mut value = doc.get("").unwrap();
1267        assert_eq!(value, Null);
1268        value = doc.get("score").unwrap();
1269        assert_eq!(value, Value::I32(1034));
1270        value = doc.get("location.state").unwrap();
1271        assert_eq!(value, Value::String("NY".to_string()));
1272        value = doc.get("location.address").unwrap();
1273        assert_eq!(
1274            value,
1275            Value::Document(doc!{
1276                line1: "40",
1277                line2: "ABC Street",
1278                house: ["1", "2", "3"],
1279                zip: 10001,
1280            })
1281        );
1282        value = doc.get("location.address.line1").unwrap();
1283        assert_eq!(value, Value::String("40".to_string()));
1284        value = doc.get("location.address.line2").unwrap();
1285        assert_eq!(value, Value::String("ABC Street".to_string()));
1286        value = doc.get("location.address.house").unwrap();
1287        assert_eq!(
1288            value,
1289            Value::Array(vec![
1290                Value::String("1".to_string()),
1291                Value::String("2".to_string()),
1292                Value::String("3".to_string())
1293            ])
1294        );
1295        value = doc.get("location.address.house.0").unwrap();
1296        assert_eq!(value, Value::String("1".to_string()));
1297        value = doc.get("location.address.house.1").unwrap();
1298        assert_eq!(value, Value::String("2".to_string()));
1299        value = doc.get("location.address.house.2").unwrap();
1300        assert_eq!(value, Value::String("3".to_string()));
1301        value = doc.get("location.address.zip").unwrap();
1302        assert_eq!(value, Value::I32(10001));
1303
1304        value = doc.get("category").unwrap();
1305        assert_eq!(
1306            value,
1307            Value::Array(vec![
1308                Value::String("food".to_string()),
1309                Value::String("produce".to_string()),
1310                Value::String("grocery".to_string())
1311            ])
1312        );
1313        value = doc.get("category.0").unwrap();
1314        assert_eq!(value, Value::String("food".to_string()));
1315        value = doc.get("category.1").unwrap();
1316        assert_eq!(value, Value::String("produce".to_string()));
1317        value = doc.get("category.2").unwrap();
1318        assert_eq!(value, Value::String("grocery".to_string()));
1319
1320        value = doc.get("obj_array").unwrap();
1321        assert_eq!(
1322            value,
1323            Value::Array(vec![
1324                Value::Document(doc!{ value: 1 }),
1325                Value::Document(doc!{ value: 2 }),
1326            ])
1327        );
1328        value = doc.get("obj_array.0").unwrap();
1329        assert_eq!(value, Value::Document(doc!{ value: 1 }));
1330        value = doc.get("obj_array.1").unwrap();
1331        assert_eq!(value, Value::Document(doc!{ value: 2 }));
1332        value = doc.get("obj_array.0.value").unwrap();
1333        assert_eq!(value, Value::I32(1));
1334        value = doc.get("obj_array.1.value").unwrap();
1335        assert_eq!(value, Value::I32(2));
1336
1337        value = doc.get("location.address.test").unwrap();
1338        assert_eq!(value, Null);
1339        assert!(doc.get("location.address.house.3").is_err());
1340        assert!(doc.get("location.address.house.-1").is_err());
1341        assert!(doc.get(".").is_err());
1342        assert!(doc.get("..").is_err());
1343        assert_eq!(doc.get("score.test").unwrap(), Null);
1344    }
1345
1346    #[test]
1347    fn test_put_null() {
1348        let mut doc = empty_document();
1349        doc.put("key", Null).unwrap();
1350        assert_eq!(doc.size(), 1);
1351        assert_eq!(doc.get("key").unwrap(), Null);
1352    }
1353
1354    #[test]
1355    fn test_put_and_get() {
1356        let mut doc = Document::new();
1357        doc.put("key", Value::I32(1)).unwrap();
1358        assert_eq!(doc.get("key").unwrap(), Value::I32(1));
1359    }
1360
1361    #[test]
1362    fn test_put_empty_key() {
1363        let mut doc = Document::new();
1364        let result = doc.put("", Value::I32(1));
1365        assert!(result.is_err());
1366    }
1367
1368    #[test]
1369    fn test_put_reserved_id() {
1370        let mut doc = Document::new();
1371        let result = doc.put(DOC_ID, Value::String("id".to_string()));
1372        assert!(result.is_err());
1373    }
1374
1375    #[test]
1376    fn test_put_id() {
1377        let mut doc = empty_document();
1378        let result = doc.put(DOC_ID, Value::String("id".to_string()));
1379        assert!(result.is_err());
1380    }
1381
1382    #[test]
1383    fn test_put_valid_nitrite_id() {
1384        let mut doc = empty_document();
1385        let result = doc.put(DOC_ID, Value::NitriteId(NitriteId::new()));
1386        assert!(result.is_ok());
1387    }
1388
1389    #[test]
1390    fn test_get_invalid_id() {
1391        // Test that document_from_map validates the _id field
1392        let mut map = BTreeMap::new();
1393        map.insert(DOC_ID.to_string(), Value::String("invalid_id".to_string()));
1394        
1395        let err = document_from_map(&map).is_err();
1396        assert!(err);
1397    }
1398
1399    #[test]
1400    fn test_get_non_existent_key() {
1401        let doc = Document::new();
1402        assert_eq!(doc.get("non_existent").unwrap(), Null);
1403    }
1404
1405    #[test]
1406    fn test_invalid_get() {
1407        let key = "first.array.-1";
1408        let doc = doc!{
1409            first: {
1410                array: [1, 2, 3],
1411            },
1412        };
1413        let err = doc.get(key).is_err();
1414        assert!(err);
1415    }
1416
1417    #[test]
1418    fn test_id() {
1419        let mut doc = empty_document();
1420        let id = doc.id().unwrap();
1421        assert!(NitriteId::valid_id(id.id_value()).unwrap());
1422        assert!(doc.has_id());
1423    }
1424
1425    #[test]
1426    fn test_fields() {
1427        let doc = doc!{
1428            key1: 1,
1429            key2: "value",
1430            key3: [1, 2, 3],
1431            key4: {
1432                key5: 5,
1433                key6: "value",
1434            },
1435        };
1436        let fields = doc.fields();
1437        assert_eq!(fields.len(), 5);
1438    }
1439
1440    #[test]
1441    fn test_has_id() {
1442        let mut doc = empty_document();
1443        assert!(!doc.has_id());
1444        doc.put(DOC_ID, Value::NitriteId(NitriteId::new())).unwrap();
1445        assert!(doc.has_id());
1446    }
1447
1448    #[test]
1449    fn test_contains_key() {
1450        let doc = set_up();
1451        assert!(doc.contains_key("score"));
1452        assert!(!doc.contains_key("non_existent"));
1453    }
1454
1455    #[test]
1456    fn test_contains_field() {
1457        let doc = set_up();
1458        assert!(doc.contains_field("location.state"));
1459        assert!(!doc.contains_field("location.country"));
1460    }
1461
1462    #[test]
1463    fn test_remove() {
1464        let mut doc = empty_document();
1465        doc.put("key", Value::I32(1)).unwrap();
1466        assert_eq!(doc.size(), 1);
1467        doc.remove("key").unwrap();
1468        assert_eq!(doc.size(), 0);
1469    }
1470
1471    #[test]
1472    fn test_size() {
1473        let doc = set_up();
1474        assert_eq!(doc.size(), 4);
1475    }
1476
1477    #[test]
1478    fn test_revision() {
1479        let mut doc = Document::new();
1480        doc.put(DOC_REVISION, Value::I32(1)).unwrap();
1481        assert_eq!(doc.revision().unwrap(), 1);
1482    }
1483
1484    #[test]
1485    fn test_source() {
1486        let mut doc = Document::new();
1487        doc.put(DOC_SOURCE, Value::String("source".to_string())).unwrap();
1488        assert_eq!(doc.source().unwrap(), "source");
1489    }
1490
1491    #[test]
1492    fn test_last_modified_since_epoch() {
1493        let mut doc = Document::new();
1494        doc.put(DOC_MODIFIED, Value::I64(123456789)).unwrap();
1495        assert_eq!(doc.last_modified_since_epoch().unwrap(), 123456789);
1496    }
1497
1498    #[test]
1499    fn test_to_map() {
1500        let doc = set_up();
1501        let map = doc.to_map();
1502        assert_eq!(map.len(), 4);
1503    }
1504
1505    #[test]
1506    fn test_iter() {
1507        let doc = doc!{
1508            key1: "value1",
1509            key2: 2,
1510        };
1511
1512        let mut iter = doc.iter();
1513        let (key, value) = iter.next().unwrap();
1514        assert_eq!(key, "key1");
1515        assert_eq!(value, Value::String("value1".to_string()));
1516
1517        let (key, value) = iter.next().unwrap();
1518        assert_eq!(key, "key2");
1519        assert_eq!(value, Value::I32(2));
1520    }
1521
1522    #[test]
1523    fn test_get_fields() {
1524        let doc = set_up();
1525        let fields = doc.fields();
1526        assert_eq!(fields.len(), 9);
1527
1528        assert!(fields.contains(&"score".to_string()));
1529        assert!(fields.contains(&"location.state".to_string()));
1530        assert!(fields.contains(&"location.city".to_string()));
1531        assert!(fields.contains(&"location.address.line1".to_string()));
1532        assert!(fields.contains(&"location.address.line2".to_string()));
1533        assert!(fields.contains(&"location.address.house".to_string()));
1534        assert!(fields.contains(&"location.address.zip".to_string()));
1535        assert!(fields.contains(&"category".to_string()));
1536        assert!(fields.contains(&"obj_array".to_string()));
1537    }
1538
1539    #[test]
1540    fn test_get_embedded_array_fields() {
1541        let doc = doc!{
1542            first: "value",
1543            second: ["1", "2"],
1544            third: Null,
1545            fourth: {
1546                first: "value",
1547                second: ["1", "2"],
1548                third: {
1549                    first: [1, 2],
1550                    second: "other",
1551                },
1552            },
1553            fifth: [
1554                {
1555                    first: "value",
1556                    second: [1, 2, 3],
1557                    third: {
1558                        first: "value",
1559                        second: [1, 2],
1560                    },
1561                    fourth: [
1562                        {
1563                            first: "value",
1564                            second: [1, 2],
1565                        },
1566                        {
1567                            first: "value",
1568                            second: [1, 2],
1569                        },
1570                    ],
1571                },
1572                {
1573                    first: "value",
1574                    second: [3, 4, 5],
1575                    third: {
1576                        first: "value",
1577                        second: [1, 2],
1578                    },
1579                    fourth: [
1580                        {
1581                            first: "value",
1582                            second: [1, 2],
1583                        },
1584                        {
1585                            first: "value",
1586                            second: [1, 2],
1587                        },
1588                    ],
1589                },
1590                {
1591                    first: "value",
1592                    second: [5, 6, 7],
1593                    third: {
1594                        first: "value",
1595                        second: [1, 2],
1596                    },
1597                    fourth: [
1598                        {
1599                            first: "value",
1600                            second: [1, 2],
1601                        },
1602                        {
1603                            first: "value",
1604                            second: [3, 4],
1605                        },
1606                    ],
1607                },
1608            ]
1609        };
1610
1611        let val = doc.get("fifth.second").unwrap();
1612        let list = val.as_array().unwrap();
1613        assert_eq!(list.len(), 7);
1614
1615        let val = doc.get("fifth.fourth.second").unwrap();
1616        let list = val.as_array().unwrap();
1617        assert_eq!(list.len(), 4);
1618
1619        let val = doc.get("fourth.third.second").unwrap();
1620        assert_eq!(val, Value::String("other".to_string()));
1621
1622        let val = doc.get("fifth.0.second.0").unwrap();
1623        assert_eq!(val, Value::I32(1));
1624
1625        let val = doc.get("fifth.1.fourth.0.second.1").unwrap();
1626        assert_eq!(val, Value::I32(2));
1627    }
1628
1629    #[test]
1630    fn test_deep_put() {
1631        let mut doc = set_up();
1632        doc.put("location.address.pin", Value::I32(700037)).unwrap();
1633        assert_eq!(doc.get("location.address.pin").unwrap(), Value::I32(700037));
1634
1635        doc.put("location.address.business.pin", Value::I32(700037))
1636            .unwrap();
1637        assert_eq!(
1638            doc.get("location.address.business.pin").unwrap(),
1639            Value::I32(700037)
1640        );
1641    }
1642
1643    #[test]
1644    fn test_deep_remove() {
1645        let mut doc = set_up();
1646        doc.remove("location.address.zip").unwrap();
1647        assert_eq!(doc.get("location.address.zip").unwrap(), Null);
1648
1649        doc.remove("location.address.line1").unwrap();
1650        assert_eq!(doc.get("location.address.line1").unwrap(), Null);
1651
1652        doc.remove("location.address.line2").unwrap();
1653        assert_eq!(doc.get("location.address.line2").unwrap(), Null);
1654
1655        doc.remove("location.address.house").unwrap();
1656        assert_eq!(doc.get("location.address.house").unwrap(), Null);
1657
1658        doc.remove("location.address").unwrap();
1659        assert_eq!(doc.get("location.address").unwrap(), Null);
1660    }
1661
1662    #[test]
1663    fn test_deep_get() {
1664        let doc = set_up();
1665        let value = doc.get("location.address.line1").unwrap();
1666        assert_eq!(value, Value::String("40".to_string()));
1667    }
1668
1669    #[test]
1670    fn test_recursive_get() {
1671        let doc = set_up();
1672        let value = doc.get("location.address.house.0").unwrap();
1673        assert_eq!(value, Value::String("1".to_string()));
1674    }
1675
1676    #[test]
1677    fn test_decompose() {
1678        let doc = doc!{
1679            some_key: [{key: 1}, {key: 2}, {key: 3}],
1680        };
1681
1682        let value = doc.get("some_key").unwrap();
1683        let array = value.as_array().unwrap();
1684        let decomposed = doc.decompose(array, &["key"]).unwrap();
1685        assert_eq!(decomposed, Value::Array(vec![Value::I32(1), Value::I32(2), Value::I32(3)]));
1686    }
1687
1688    #[test]
1689    fn test_deep_put_invalid_field() {
1690        let mut doc = empty_document();
1691        let result = doc.put("..invalid..field", Value::I32(1));
1692        assert!(result.is_err());
1693    }
1694
1695    #[test]
1696    fn test_deep_remove_invalid_field() {
1697        let mut doc = empty_document();
1698        let result = doc.remove("..invalid..field");
1699        assert!(result.is_err());
1700    }
1701
1702    #[test]
1703    fn test_merge_documents() {
1704        let mut doc1 = doc!{
1705            "key1": "value1",
1706            "nested": {
1707                "key2": "value2",
1708            },
1709        };
1710
1711        let doc2 = doc!{
1712            "key3": "value3",
1713            "nested": {
1714                "key4": "value4",
1715            },
1716        };
1717
1718        doc1.merge(&doc2).unwrap();
1719        assert_eq!(doc1.size(), 3);
1720        assert_eq!(
1721            doc1.get("key1").unwrap(),
1722            Value::String("value1".to_string())
1723        );
1724        assert_eq!(
1725            doc1.get("key3").unwrap(),
1726            Value::String("value3".to_string())
1727        );
1728        assert_eq!(
1729            doc1.get("nested.key2").unwrap(),
1730            Value::String("value2".to_string())
1731        );
1732        assert_eq!(
1733            doc1.get("nested.key4").unwrap(),
1734            Value::String("value4".to_string())
1735        );
1736    }
1737
1738    #[test]
1739    fn test_display() {
1740        let doc = doc!{
1741            key1: "value1",
1742            key2: 2,
1743        };
1744
1745        let display = format!("{}", doc);
1746        assert!(display.contains("\"key1\": \"value1\""));
1747        assert!(display.contains("\"key2\": 2"));
1748    }
1749
1750    #[test]
1751    fn test_debug() {
1752        let doc = doc!{
1753            key1: "value1",
1754            key2: 2,
1755        };
1756
1757        let debug = format!("{:?}", doc);
1758        assert!(debug.contains("\"key1\": string(\"value1\")"));
1759        assert!(debug.contains("\"key2\": i32(2)"));
1760    }
1761
1762    #[test]
1763    fn test_put_invalid_id() {
1764        let mut doc = empty_document();
1765        let result = doc.put(DOC_ID, Value::String("invalid_id".to_string()));
1766        assert!(result.is_err());
1767    }
1768
1769    #[test]
1770    fn test_get_invalid_key() {
1771        let doc = empty_document();
1772        let result = doc.get("invalid.key");
1773        assert!(result.is_ok());
1774        assert_eq!(result.unwrap(), Null);
1775    }
1776
1777    #[test]
1778    fn test_remove_invalid_key() {
1779        let mut doc = empty_document();
1780        let result = doc.remove("invalid.key");
1781        assert!(result.is_ok());
1782    }
1783
1784    #[test]
1785    fn test_merge_empty_document() {
1786        let mut doc1 = empty_document();
1787        let doc2 = empty_document();
1788        doc1.merge(&doc2).unwrap();
1789        assert_eq!(doc1.size(), 0);
1790    }
1791
1792    #[test]
1793    fn test_get_invalid_array_index() {
1794        let doc = doc!{
1795            key: [1, 2, 3],
1796        };
1797
1798        let result = doc.get("key.-1");
1799        assert!(result.is_err());
1800    }
1801
1802    #[test]
1803    fn test_remove_invalid_array_index() {
1804        let mut doc = doc!{
1805            key: [1, 2, 3],
1806        };
1807
1808        let result = doc.remove("key.-1");
1809        assert!(result.is_err());
1810    }
1811
1812    #[test]
1813    fn test_merge_conflicting_keys() {
1814        let mut doc1 = doc!{
1815            key1: "value1",
1816            key2: "value2",
1817        };
1818
1819        let doc2 = doc!{
1820            key2: "value3",
1821            key3: "value4",
1822        };
1823
1824        doc1.merge(&doc2).unwrap();
1825        assert_eq!(doc1.size(), 3);
1826        assert_eq!(
1827            doc1.get("key1").unwrap(),
1828            Value::String("value1".to_string())
1829        );
1830        assert_eq!(
1831            doc1.get("key2").unwrap(),
1832            Value::String("value3".to_string())
1833        );
1834        assert_eq!(
1835            doc1.get("key3").unwrap(),
1836            Value::String("value4".to_string())
1837        );
1838    }
1839
1840    #[test]
1841    fn test_deep_put_invalid_path() {
1842        let mut doc = empty_document();
1843        let result = doc.put("key..key", Value::I32(1));
1844        assert!(result.is_err());
1845    }
1846
1847    #[test]
1848    fn test_deep_get_invalid_path() {
1849        let doc = set_up();
1850        let result = doc.get("location..key");
1851        assert!(result.is_err());
1852    }
1853
1854    #[test]
1855    fn contains_field_with_existing_field() {
1856        let doc = set_up();
1857        assert!(doc.contains_field("location.state"));
1858    }
1859
1860    #[test]
1861    fn contains_field_with_non_existing_field() {
1862        let doc = set_up();
1863        assert!(!doc.contains_field("location.country"));
1864    }
1865
1866    #[test]
1867    fn revision_with_existing_revision() {
1868        let mut doc = empty_document();
1869        doc.put(DOC_REVISION, Value::I32(1)).unwrap();
1870        assert_eq!(doc.revision().unwrap(), 1);
1871    }
1872
1873    #[test]
1874    fn revision_with_non_existing_revision() {
1875        let doc = empty_document();
1876        assert_eq!(doc.revision().unwrap(), 0);
1877    }
1878
1879    #[test]
1880    fn source_with_existing_source() {
1881        let mut doc = empty_document();
1882        doc.put(DOC_SOURCE, Value::String("source".to_string()))
1883            .unwrap();
1884        assert_eq!(doc.source().unwrap(), "source");
1885    }
1886
1887    #[test]
1888    fn source_with_non_existing_source() {
1889        let doc = empty_document();
1890        assert_eq!(doc.source().unwrap(), "");
1891    }
1892
1893    #[test]
1894    fn last_modified_since_epoch_with_existing_modified() {
1895        let mut doc = empty_document();
1896        doc.put(DOC_MODIFIED, Value::I64(123456789)).unwrap();
1897        assert_eq!(doc.last_modified_since_epoch().unwrap(), 123456789);
1898    }
1899
1900    #[test]
1901    fn last_modified_since_epoch_with_non_existing_modified() {
1902        let doc = empty_document();
1903        assert_eq!(doc.last_modified_since_epoch().unwrap(), 0);
1904    }
1905
1906    #[test]
1907    fn test_macro() {
1908        let string_key = "c".to_string();
1909        let document = doc!{
1910            s: string_key,
1911            a: 12,
1912            b: "c",
1913            "d": [1, 2, 3],
1914            e: ["f", "g"],
1915            h: {
1916                i: 10,
1917                j: [1, 2, 3],
1918            },
1919            k: [
1920                {
1921                    l: 15,
1922                    m: [10, 15],
1923                    "n": {
1924                        o: 1.25,
1925                    },
1926                },
1927                {
1928                    p: 15,
1929                    q: [
1930                        {
1931                            r: "45",
1932                            s: 1569,
1933                        },
1934                        {
1935                            t: 20,
1936                            u: 1.25,
1937                        },
1938                    ],
1939                }
1940            ],
1941            u: [
1942                ["v", "w"],
1943                ["x", "y", "z"],
1944            ],
1945            v: {
1946                w: {
1947                    x: {
1948                        y: {
1949                            z: true,
1950                        }
1951                    }
1952                }
1953            }
1954        };
1955
1956        let mut doc2 = empty_document();
1957        doc2.put("s", Value::String("c".to_string())).unwrap();
1958        doc2.put("a", Value::I32(12)).unwrap();
1959        doc2.put("b", Value::String("c".to_string())).unwrap();
1960        doc2.put(
1961            "d",
1962            Value::Array(vec![Value::I32(1), Value::I32(2), Value::I32(3)]),
1963        )
1964            .unwrap();
1965        doc2.put(
1966            "e",
1967            Value::Array(vec![
1968                Value::String("f".to_string()),
1969                Value::String("g".to_string()),
1970            ]),
1971        )
1972            .unwrap();
1973        doc2.put("h", Value::Document(doc!{ i: 10, j: [1, 2, 3] }))
1974            .unwrap();
1975        doc2.put(
1976            "k",
1977            Value::Array(vec![
1978                Value::Document(doc!{ l: 15, m: [10, 15], "n": { o: 1.25 } }),
1979                Value::Document(doc!{ p: 15, q: [
1980                { r: "45", s: 1569 },
1981                { t: 20, u: 1.25 },
1982            ] }),
1983            ]),
1984        )
1985            .unwrap();
1986
1987        doc2.put(
1988            "u",
1989            Value::Array(vec![
1990                Value::Array(vec![
1991                    Value::String("v".to_string()),
1992                    Value::String("w".to_string()),
1993                ]),
1994                Value::Array(vec![
1995                    Value::String("x".to_string()),
1996                    Value::String("y".to_string()),
1997                    Value::String("z".to_string()),
1998                ]),
1999            ]),
2000        )
2001            .unwrap();
2002
2003        doc2.put("v", Value::Document(doc!{ w: { x: { y: { z: true } } } }))
2004            .unwrap();
2005
2006        assert_eq!(document, doc2);
2007    }
2008
2009    #[test]
2010    fn test_empty_document_macro() {
2011        let doc = doc!{};
2012        assert!(doc.is_empty());
2013    }
2014
2015    #[test]
2016    fn test_document_with_key_value_string() {
2017        let doc = doc!{
2018            key: "value",
2019        };
2020        assert_eq!(doc.size(), 1);
2021        assert_eq!(doc.get("key").unwrap(), Value::String("value".to_string()));
2022    }
2023
2024    #[test]
2025    fn test_nested_document_macro() {
2026        let doc = doc!{
2027            key1: "value1",
2028            key2: {
2029                key3: "value3",
2030            },
2031        };
2032        assert_eq!(doc.size(), 2);
2033        assert_eq!(
2034            doc.get("key1").unwrap(),
2035            Value::String("value1".to_string())
2036        );
2037        assert_eq!(
2038            doc.get("key2.key3").unwrap(),
2039            Value::String("value3".to_string())
2040        );
2041    }
2042
2043    #[test]
2044    fn test_array_in_document_macro() {
2045        let doc = doc!{
2046            key1: "value1",
2047            key2: [1, 2, 3],
2048        };
2049        assert_eq!(doc.size(), 2);
2050        assert_eq!(
2051            doc.get("key1").unwrap(),
2052            Value::String("value1".to_string())
2053        );
2054        assert_eq!(
2055            doc.get("key2").unwrap(),
2056            Value::Array(vec![Value::I32(1), Value::I32(2), Value::I32(3)])
2057        );
2058    }
2059
2060    #[test]
2061    fn test_complex_document_macro() {
2062        let document = doc!{
2063            key1: "value1",
2064            key2: {
2065                nested_key1: "nested_value",
2066                nested_key2: [10, 20, 30]
2067            },
2068            key3: [true, false, {
2069                "deep_nested_key": "deep_value"
2070            }]
2071        };
2072
2073        assert_eq!(document.size(), 3);
2074        assert_eq!(
2075            document.get("key1").unwrap(),
2076            Value::String("value1".to_string())
2077        );
2078
2079        let binding = document.get("key2").unwrap();
2080        let nested_doc = binding.as_document().unwrap();
2081        assert_eq!(nested_doc.size(), 2);
2082        assert_eq!(
2083            nested_doc.get("nested_key1").unwrap(),
2084            Value::String("nested_value".to_string())
2085        );
2086
2087        let nested_array = nested_doc.get("nested_key2").unwrap();
2088        let array = nested_array.as_array().unwrap();
2089        assert_eq!(array.len(), 3);
2090        assert_eq!(array[0], Value::I32(10));
2091        assert_eq!(array[1], Value::I32(20));
2092        assert_eq!(array[2], Value::I32(30));
2093
2094        let binding = document.get("key3").unwrap();
2095        let array = binding.as_array().unwrap();
2096        assert_eq!(array.len(), 3);
2097        assert_eq!(array[0], Value::Bool(true));
2098        assert_eq!(array[1], Value::Bool(false));
2099
2100        let binding = &array[2];
2101        let nested_doc = binding.as_document().unwrap();
2102        assert_eq!(nested_doc.size(), 1);
2103        assert_eq!(
2104            nested_doc.get("deep_nested_key").unwrap(),
2105            Value::String("deep_value".to_string())
2106        );
2107    }
2108
2109    // Tests for recursive_get with idiomatic pattern matching
2110    #[test]
2111    fn test_recursive_get_null_value() {
2112        let doc = Document::new();
2113        let result = doc.recursive_get(None, &[]);
2114        assert_eq!(result.unwrap(), Null);
2115    }
2116
2117    #[test]
2118    fn test_recursive_get_simple_value() {
2119        let doc = doc!{
2120            "name": "Alice",
2121            "age": 25
2122        };
2123
2124        let value = doc.get("name").unwrap();
2125        assert_eq!(value, Value::String("Alice".to_string()));
2126
2127        let value = doc.get("age").unwrap();
2128        assert_eq!(value, Value::I32(25));
2129    }
2130
2131    #[test]
2132    fn test_recursive_get_nested_document() {
2133        let doc = doc!{
2134            "user": {
2135                "profile": {
2136                    "name": "Bob",
2137                    "age": 30
2138                }
2139            }
2140        };
2141
2142        let value = doc.get("user").unwrap();
2143        assert!(matches!(value, Value::Document(_)));
2144
2145        let value = doc.get("user.profile").unwrap();
2146        assert!(matches!(value, Value::Document(_)));
2147
2148        let value = doc.get("user.profile.name").unwrap();
2149        assert_eq!(value, Value::String("Bob".to_string()));
2150    }
2151
2152    #[test]
2153    fn test_recursive_get_array_index() {
2154        let doc = doc!{
2155            "items": [
2156                {"name": "Item 1"},
2157                {"name": "Item 2"},
2158                {"name": "Item 3"}
2159            ]
2160        };
2161
2162        let value = doc.get("items.0").unwrap();
2163        assert!(matches!(value, Value::Document(_)));
2164
2165        let value = doc.get("items.0.name").unwrap();
2166        assert_eq!(value, Value::String("Item 1".to_string()));
2167
2168        let value = doc.get("items.2.name").unwrap();
2169        assert_eq!(value, Value::String("Item 3".to_string()));
2170    }
2171
2172    #[test]
2173    fn test_recursive_get_nonexistent_path() {
2174        let doc = doc!{
2175            "name": "Charlie",
2176            "age": 35
2177        };
2178
2179        let value = doc.get("nonexistent").unwrap();
2180        assert_eq!(value, Null);
2181
2182        let value = doc.get("name.nested").unwrap();
2183        assert_eq!(value, Null);
2184    }
2185
2186    #[test]
2187    fn test_recursive_get_deep_nesting() {
2188        let doc = doc!{
2189            "level1": {
2190                "level2": {
2191                    "level3": {
2192                        "level4": {
2193                            "value": "deep"
2194                        }
2195                    }
2196                }
2197            }
2198        };
2199
2200        let value = doc.get("level1.level2.level3.level4.value").unwrap();
2201        assert_eq!(value, Value::String("deep".to_string()));
2202    }
2203
2204    #[test]
2205    fn test_recursive_get_mixed_types() {
2206        let doc = doc!{
2207            "name": "David",
2208            "age": 28,
2209            "tags": ["tag1", "tag2"],
2210            "meta": {
2211                "created": "2025-01-01"
2212            }
2213        };
2214
2215        assert_eq!(doc.get("name").unwrap(), Value::String("David".to_string()));
2216        assert_eq!(doc.get("age").unwrap(), Value::I32(28));
2217        assert!(matches!(doc.get("tags").unwrap(), Value::Array(_)));
2218        assert!(matches!(doc.get("meta").unwrap(), Value::Document(_)));
2219    }
2220
2221    #[test]
2222    fn bench_get_top_level_key() {
2223        let doc = doc!{
2224            key1: "value1",
2225            key2: "value2",
2226            key3: "value3",
2227            key4: "value4",
2228            key5: "value5",
2229        };
2230
2231        let start = std::time::Instant::now();
2232        for _ in 0..10000 {
2233            let _ = doc.get("key1");
2234        }
2235        let elapsed = start.elapsed();
2236        println!("10000 top-level get calls: {:?}", elapsed);
2237        assert!(elapsed.as_millis() < 500);
2238    }
2239
2240    #[test]
2241    fn bench_get_embedded_key() {
2242        let doc = doc!{
2243            level1: {
2244                level2: {
2245                    level3: "value"
2246                }
2247            }
2248        };
2249
2250        let start = std::time::Instant::now();
2251        for _ in 0..1000 {
2252            let _ = doc.get("level1.level2.level3");
2253        }
2254        let elapsed = start.elapsed();
2255        println!("1000 embedded get calls: {:?}", elapsed);
2256        assert!(elapsed.as_millis() < 200);
2257    }
2258
2259    #[test]
2260    fn bench_put_operations() {
2261        let start = std::time::Instant::now();
2262        for i in 0..1000 {
2263            let mut doc = Document::new();
2264            doc.put(format!("key{}", i), Value::I32(i)).ok();
2265        }
2266        let elapsed = start.elapsed();
2267        println!("1000 put operations: {:?}", elapsed);
2268        assert!(elapsed.as_millis() < 300);
2269    }
2270
2271    #[test]
2272    fn bench_merge_documents() {
2273        let start = std::time::Instant::now();
2274        for _ in 0..100 {
2275            let mut doc1 = doc!{
2276                key1: "value1",
2277                nested: {
2278                    key2: "value2",
2279                }
2280            };
2281            let doc2 = doc!{
2282                key3: "value3",
2283                nested: {
2284                    key4: "value4",
2285                }
2286            };
2287            doc1.merge(&doc2).ok();
2288        }
2289        let elapsed = start.elapsed();
2290        println!("100 merge operations: {:?}", elapsed);
2291        assert!(elapsed.as_millis() < 200);
2292    }
2293
2294    #[test]
2295    fn bench_fields_collection() {
2296        let doc = doc!{
2297            key1: "value1",
2298            key2: 2,
2299            nested: {
2300                key3: "value3",
2301                deep: {
2302                    key4: "value4"
2303                }
2304            },
2305            array: [1, 2, 3]
2306        };
2307
2308        let start = std::time::Instant::now();
2309        for _ in 0..1000 {
2310            let _ = doc.fields();
2311        }
2312        let elapsed = start.elapsed();
2313        println!("1000 fields() calls: {:?}", elapsed);
2314        assert!(elapsed.as_millis() < 300);
2315    }
2316
2317    // Tests for expression support in doc! macro
2318    #[test]
2319    fn test_doc_macro_with_variables() {
2320        let name = "Alice";
2321        let age = 30;
2322        let city = String::from("NYC");
2323
2324        let doc = doc!{
2325            name: name,
2326            age: age,
2327            city: city
2328        };
2329
2330        assert_eq!(doc.get("name").unwrap(), Value::String("Alice".to_string()));
2331        assert_eq!(doc.get("age").unwrap(), Value::I32(30));
2332        assert_eq!(doc.get("city").unwrap(), Value::String("NYC".to_string()));
2333    }
2334
2335    #[test]
2336    fn test_doc_macro_with_expressions() {
2337        let base = 100;
2338        let multiplier = 2;
2339
2340        let doc = doc!{
2341            computed: (base * multiplier),
2342            sum: (10 + 20 + 30),
2343            concat: (format!("Hello {}", "World"))
2344        };
2345
2346        assert_eq!(doc.get("computed").unwrap(), Value::I32(200));
2347        assert_eq!(doc.get("sum").unwrap(), Value::I32(60));
2348        assert_eq!(doc.get("concat").unwrap(), Value::String("Hello World".to_string()));
2349    }
2350
2351    #[test]
2352    fn test_doc_macro_with_function_calls() {
2353        fn get_name() -> &'static str {
2354            "Bob"
2355        }
2356
2357        fn calculate_score() -> i32 {
2358            42
2359        }
2360
2361        let doc = doc!{
2362            name: (get_name()),
2363            score: (calculate_score()),
2364            length: ("hello".len())
2365        };
2366
2367        assert_eq!(doc.get("name").unwrap(), Value::String("Bob".to_string()));
2368        assert_eq!(doc.get("score").unwrap(), Value::I32(42));
2369        assert_eq!(doc.get("length").unwrap(), Value::U64(5));
2370    }
2371
2372    #[test]
2373    fn test_doc_macro_with_mixed_expressions_and_nested() {
2374        let user_name = "Charlie";
2375        let base_score = 50;
2376
2377        let doc = doc!{
2378            user: {
2379                name: user_name,
2380                score: (base_score * 2)
2381            },
2382            tags: ["admin", user_name],
2383            values: [1, (2 + 3), 6]
2384        };
2385
2386        assert_eq!(doc.get("user.name").unwrap(), Value::String("Charlie".to_string()));
2387        assert_eq!(doc.get("user.score").unwrap(), Value::I32(100));
2388        
2389        let tags = doc.get("tags").unwrap();
2390        let tags_arr = tags.as_array().unwrap();
2391        assert_eq!(tags_arr[0], Value::String("admin".to_string()));
2392        assert_eq!(tags_arr[1], Value::String("Charlie".to_string()));
2393
2394        let values = doc.get("values").unwrap();
2395        let values_arr = values.as_array().unwrap();
2396        assert_eq!(values_arr[0], Value::I32(1));
2397        assert_eq!(values_arr[1], Value::I32(5));
2398        assert_eq!(values_arr[2], Value::I32(6));
2399    }
2400
2401    #[test]
2402    fn test_doc_macro_empty_new_syntax() {
2403        let doc = doc!{};
2404        assert!(doc.is_empty());
2405    }
2406
2407    // Additional tests for coverage improvement
2408    
2409    #[test]
2410    fn test_merge_nested_document_in_place() {
2411        // Test the path where nested document merge happens in place
2412        let mut doc1 = doc!{
2413            nested: {
2414                key1: "value1",
2415                inner: {
2416                    a: 1
2417                }
2418            }
2419        };
2420
2421        let doc2 = doc!{
2422            nested: {
2423                key2: "value2",
2424                inner: {
2425                    b: 2
2426                }
2427            }
2428        };
2429
2430        doc1.merge(&doc2).unwrap();
2431        
2432        // Verify the merge happened correctly
2433        assert_eq!(doc1.get("nested.key1").unwrap(), Value::String("value1".to_string()));
2434        assert_eq!(doc1.get("nested.key2").unwrap(), Value::String("value2".to_string()));
2435        assert_eq!(doc1.get("nested.inner.a").unwrap(), Value::I32(1));
2436        assert_eq!(doc1.get("nested.inner.b").unwrap(), Value::I32(2));
2437    }
2438
2439    #[test]
2440    fn test_merge_document_overwrites_non_document() {
2441        // Test when trying to merge a document value into a non-document field
2442        let mut doc1 = doc!{
2443            field: "string_value"
2444        };
2445
2446        let doc2 = doc!{
2447            field: {
2448                nested: "value"
2449            }
2450        };
2451
2452        doc1.merge(&doc2).unwrap();
2453        
2454        // The document should overwrite the string
2455        assert_eq!(doc1.get("field.nested").unwrap(), Value::String("value".to_string()));
2456    }
2457
2458    #[test]
2459    fn test_fields_with_prefix() {
2460        // Test get_fields_internal with a prefix (nested document fields)
2461        let doc = doc!{
2462            level1: {
2463                level2: {
2464                    leaf: "value"
2465                }
2466            }
2467        };
2468
2469        let fields = doc.fields();
2470        assert!(fields.contains(&"level1.level2.leaf".to_string()));
2471    }
2472
2473    #[test]
2474    fn test_iterator_size_hint() {
2475        let doc = doc!{
2476            key1: "value1",
2477            key2: "value2",
2478            key3: "value3"
2479        };
2480
2481        let iter = doc.iter();
2482        let (lower, upper) = iter.size_hint();
2483        
2484        assert_eq!(lower, 3);
2485        assert_eq!(upper, Some(3));
2486    }
2487
2488    #[test]
2489    fn test_remove_array_element_by_index() {
2490        let mut doc = doc!{
2491            items: [1, 2, 3, 4, 5]
2492        };
2493
2494        // Remove element at index 2
2495        doc.remove("items.2").unwrap();
2496        
2497        let items = doc.get("items").unwrap();
2498        let arr = items.as_array().unwrap();
2499        assert_eq!(arr.len(), 4);
2500        assert_eq!(arr[0], Value::I32(1));
2501        assert_eq!(arr[1], Value::I32(2));
2502        assert_eq!(arr[2], Value::I32(4)); // Previously index 3
2503        assert_eq!(arr[3], Value::I32(5)); // Previously index 4
2504    }
2505
2506    #[test]
2507    fn test_remove_nested_document_in_array() {
2508        let mut doc = doc!{
2509            items: [
2510                { name: "item1", value: 1 },
2511                { name: "item2", value: 2 },
2512                { name: "item3", value: 3 }
2513            ]
2514        };
2515
2516        // Remove a field from nested document in array
2517        doc.remove("items.1.value").unwrap();
2518        
2519        // Check the nested document still exists but without the removed field
2520        let item1 = doc.get("items.1").unwrap();
2521        let item_doc = item1.as_document().unwrap();
2522        assert_eq!(item_doc.size(), 1);
2523        assert_eq!(item_doc.get("name").unwrap(), Value::String("item2".to_string()));
2524        assert_eq!(item_doc.get("value").unwrap(), Null);
2525    }
2526
2527    #[test]
2528    fn test_remove_entire_nested_document_in_array_when_empty() {
2529        let mut doc = doc!{
2530            items: [
2531                { only_field: "value" }
2532            ]
2533        };
2534
2535        // Remove the only field, which should remove the document from array
2536        doc.remove("items.0.only_field").unwrap();
2537        
2538        // The array should now be empty since the only document became empty
2539        let items = doc.get("items").unwrap();
2540        let arr = items.as_array().unwrap();
2541        assert_eq!(arr.len(), 0);
2542    }
2543
2544    #[test]
2545    fn test_remove_array_out_of_bounds() {
2546        let mut doc = doc!{
2547            items: [1, 2, 3]
2548        };
2549
2550        // Try to remove at out of bounds index
2551        let result = doc.remove("items.10");
2552        assert!(result.is_err());
2553    }
2554
2555    #[test]
2556    fn test_remove_array_negative_index() {
2557        let mut doc = doc!{
2558            items: [1, 2, 3]
2559        };
2560
2561        // Try to remove at negative index
2562        let result = doc.remove("items.-1");
2563        assert!(result.is_err());
2564    }
2565
2566    #[test]
2567    fn test_remove_array_invalid_index_string() {
2568        let mut doc = doc!{
2569            items: [1, 2, 3]
2570        };
2571
2572        // Try to remove with non-numeric index
2573        let result = doc.remove("items.abc");
2574        assert!(result.is_err());
2575    }
2576
2577    #[test]
2578    fn test_remove_non_existent_nested_path() {
2579        let mut doc = doc!{
2580            existing: "value"
2581        };
2582
2583        // Removing a non-existent path should succeed silently
2584        let result = doc.remove("non_existent.nested.path");
2585        assert!(result.is_ok());
2586    }
2587
2588    #[test]
2589    fn test_deep_put_creates_nested_structure() {
2590        let mut doc = doc!{};
2591        
2592        // Put a deeply nested value - should create intermediate documents
2593        doc.put("a.b.c.d", Value::String("deep".to_string())).unwrap();
2594        
2595        assert_eq!(doc.get("a.b.c.d").unwrap(), Value::String("deep".to_string()));
2596    }
2597
2598    #[test]
2599    fn test_deep_put_into_existing_nested_document() {
2600        let mut doc = doc!{
2601            existing: {
2602                nested: {
2603                    key1: "value1"
2604                }
2605            }
2606        };
2607        
2608        // Put into existing nested structure
2609        doc.put("existing.nested.key2", Value::String("value2".to_string())).unwrap();
2610        
2611        assert_eq!(doc.get("existing.nested.key1").unwrap(), Value::String("value1".to_string()));
2612        assert_eq!(doc.get("existing.nested.key2").unwrap(), Value::String("value2".to_string()));
2613    }
2614
2615    #[test]
2616    fn test_fields_skips_reserved_fields() {
2617        let mut doc = doc!{
2618            regular_field: "value"
2619        };
2620        
2621        // Manually add reserved fields using put
2622        doc.put(DOC_ID, Value::NitriteId(NitriteId::new())).unwrap();
2623        doc.put(DOC_REVISION, Value::I32(1)).unwrap();
2624        doc.put(DOC_SOURCE, Value::String("source".to_string())).unwrap();
2625        doc.put(DOC_MODIFIED, Value::I64(12345)).unwrap();
2626        
2627        let fields = doc.fields();
2628        
2629        // Only the regular field should be in the fields list
2630        assert_eq!(fields.len(), 1);
2631        assert!(fields.contains(&"regular_field".to_string()));
2632        assert!(!fields.contains(&DOC_ID.to_string()));
2633        assert!(!fields.contains(&DOC_REVISION.to_string()));
2634    }
2635
2636    #[test]
2637    fn test_fields_skips_empty_keys() {
2638        let doc = doc!{
2639            valid_key: "value"
2640        };
2641        
2642        // Note: We cannot directly add empty keys through put() as it validates against empty keys
2643        // The empty key validation in put() prevents this, which is correct behavior
2644        
2645        let fields = doc.fields();
2646        
2647        // Only the valid key should be in the fields list
2648        assert_eq!(fields.len(), 1);
2649        assert!(fields.contains(&"valid_key".to_string()));
2650    }
2651
2652    #[test]
2653    fn test_to_pretty_json_empty() {
2654        let doc = doc!{};
2655        let json = doc.to_pretty_json(0);
2656        assert_eq!(json, "{}");
2657    }
2658
2659    #[test]
2660    fn test_to_debug_string_empty() {
2661        let doc = doc!{};
2662        let debug = doc.to_debug_string(0);
2663        assert_eq!(debug, "{}");
2664    }
2665
2666    #[test]
2667    fn test_to_pretty_json_with_indent() {
2668        let doc = doc!{
2669            key: "value"
2670        };
2671        let json = doc.to_pretty_json(2);
2672        assert!(json.contains("    \"key\"")); // 4 spaces (2 + 2)
2673    }
2674
2675    #[test]
2676    fn test_to_debug_string_with_indent() {
2677        let doc = doc!{
2678            key: "value"
2679        };
2680        let debug = doc.to_debug_string(2);
2681        assert!(debug.contains("    \"key\"")); // 4 spaces (2 + 2)
2682    }
2683
2684    #[test]
2685    fn test_contains_field_embedded_path() {
2686        // Test the else branch of contains_field where key is not a direct key
2687        // but exists as an embedded field path
2688        let mut doc = doc!{
2689            outer: "temp"
2690        };
2691        
2692        // Create nested document
2693        let inner = doc!{
2694            inner: "value"
2695        };
2696        doc.put("outer", inner).unwrap();
2697        
2698        // Direct key check
2699        assert!(doc.contains_field("outer"));
2700        
2701        // Embedded field check (this exercises the else branch)
2702        assert!(doc.contains_field("outer.inner"));
2703        
2704        // Non-existent embedded field
2705        assert!(!doc.contains_field("outer.nonexistent"));
2706        assert!(!doc.contains_field("nonexistent.path"));
2707    }
2708
2709    #[test]
2710    fn test_deep_get_non_embedded_key() {
2711        // Test deep_get when key is not embedded (doesn't contain separator)
2712        // This should hit the !is_embedded() branch returning Ok(Value::Null)
2713        let doc = doc!{
2714            name: "test"
2715        };
2716        
2717        // When we call get_by_embedded_key on a non-embedded key,
2718        // deep_get checks is_embedded first
2719        // But we need to call the internal deep_get method
2720        // The deep_get returns Null for non-embedded keys
2721        
2722        // Get a key that doesn't exist and isn't embedded
2723        let result = doc.get("nonexistent");
2724        assert!(result.is_ok());
2725        assert_eq!(result.unwrap(), Value::Null);
2726    }
2727
2728    
2729    #[cfg(test)]
2730    mod custom_separator_test {
2731        use super::*;
2732        use crate::nitrite_config::NitriteConfig;
2733
2734        #[test]
2735        #[cfg_attr(not(feature = "custom_separator"), ignore)]
2736        fn custom_separator_test_remove_array() {
2737            NitriteConfig::new().set_field_separator(":").expect("Failed to set separator");
2738            let mut doc = set_up();
2739            assert_eq!(
2740                doc.get("location:address:house")
2741                    .unwrap()
2742                    .as_array()
2743                    .unwrap()
2744                    .len(),
2745                3
2746            );
2747
2748            doc.remove("location:address:house:0").unwrap();
2749            assert_eq!(
2750                doc.get("location:address:house")
2751                    .unwrap()
2752                    .as_array()
2753                    .unwrap()
2754                    .len(),
2755                2
2756            );
2757
2758            assert_eq!(doc.get("obj_array").unwrap().as_array().unwrap().len(), 2);
2759            doc.remove("obj_array:0:value").unwrap();
2760            assert_eq!(doc.get("obj_array").unwrap().as_array().unwrap().len(), 1);
2761            assert_eq!(
2762                doc.get("obj_array:0")
2763                    .unwrap()
2764                    .as_document()
2765                    .unwrap()
2766                    .size(),
2767                1
2768            );
2769        }
2770
2771        #[test]
2772        #[cfg_attr(not(feature = "custom_separator"), ignore)]
2773        fn custom_separator_test_remove() {
2774            NitriteConfig::new().set_field_separator(":").expect("Failed to set separator");
2775            let mut doc = set_up();
2776            assert_eq!(
2777                doc.get("location:address")
2778                    .unwrap()
2779                    .as_document()
2780                    .unwrap()
2781                    .size(),
2782                4
2783            );
2784            doc.remove("location:address:line1").unwrap();
2785            assert_eq!(
2786                doc.get("location:address")
2787                    .unwrap()
2788                    .as_document()
2789                    .unwrap()
2790                    .size(),
2791                3
2792            );
2793        }
2794
2795        #[test]
2796        #[cfg_attr(not(feature = "custom_separator"), ignore)]
2797        fn custom_separator_test_get() {
2798            NitriteConfig::new().set_field_separator(":").expect("Failed to set separator");
2799
2800            let doc = set_up();
2801            let mut value = doc.get("").unwrap();
2802            assert_eq!(value, Null);
2803            value = doc.get("score").unwrap();
2804            assert_eq!(value, Value::I32(1034));
2805            value = doc.get("location:state").unwrap();
2806            assert_eq!(value, Value::String("NY".to_string()));
2807            value = doc.get("location:address").unwrap();
2808            assert_eq!(
2809                value,
2810                Value::Document(doc!{
2811                    line1: "40",
2812                    line2: "ABC Street",
2813                    house: ["1", "2", "3"],
2814                    zip: 10001,
2815                })
2816            );
2817            value = doc.get("location:address:line1").unwrap();
2818            assert_eq!(value, Value::String("40".to_string()));
2819            value = doc.get("location:address:line2").unwrap();
2820            assert_eq!(value, Value::String("ABC Street".to_string()));
2821            value = doc.get("location:address:house:0").unwrap();
2822            assert_eq!(value, Value::String("1".to_string()));
2823            value = doc.get("location:address:house:1").unwrap();
2824            assert_eq!(value, Value::String("2".to_string()));
2825            value = doc.get("location:address:house:2").unwrap();
2826            assert_eq!(value, Value::String("3".to_string()));
2827            value = doc.get("location:address:zip").unwrap();
2828            assert_eq!(value, Value::I32(10001));
2829
2830            value = doc.get("category:0").unwrap();
2831            assert_eq!(value, Value::String("food".to_string()));
2832            value = doc.get("category:1").unwrap();
2833            assert_eq!(value, Value::String("produce".to_string()));
2834            value = doc.get("category:2").unwrap();
2835            assert_eq!(value, Value::String("grocery".to_string()));
2836
2837            value = doc.get("obj_array:0").unwrap();
2838            assert_eq!(value, Value::Document(doc!{ value: 1 }));
2839            value = doc.get("obj_array:1").unwrap();
2840            assert_eq!(value, Value::Document(doc!{ value: 2 }));
2841            value = doc.get("obj_array:0:value").unwrap();
2842            assert_eq!(value, Value::I32(1));
2843            value = doc.get("obj_array:1:value").unwrap();
2844            assert_eq!(value, Value::I32(2));
2845
2846            value = doc.get("location:address:test").unwrap();
2847            assert_eq!(value, Null);
2848            assert!(doc.get("location:address:house:3").is_err());
2849            assert!(doc.get("location:address:house:-1").is_err());
2850            assert!(doc.get(":").is_err());
2851            assert!(doc.get("::").is_err());
2852            assert_eq!(doc.get("score:test").unwrap(), Null);
2853        }
2854
2855        #[test]
2856        #[cfg_attr(not(feature = "custom_separator"), ignore)]
2857        fn custom_separator_test_default_separator_fails() {
2858            NitriteConfig::new().set_field_separator(":").expect("Failed to set separator");
2859            let doc = set_up();
2860            let value = doc.get("location.address.house.0").unwrap();
2861            assert_eq!(value, Null);
2862
2863            let value = doc.get("location:address:house:0").unwrap();
2864            assert_eq!(value, Value::String("1".to_string()));
2865        }
2866    }
2867}