1use crate::drive::document::index_level_tree_types::distinct_estimated_keys;
2use crate::error::drive::DriveError;
3use crate::error::fee::FeeError;
4use crate::error::Error;
5use crate::util::object_size_info::DriveKeyInfo::{Key, KeySize};
6use crate::util::object_size_info::KeyValueInfo::{KeyRefRequest, KeyValueMaxSize};
7use crate::util::object_size_info::{DriveKeyInfo, KeyValueInfo};
8use crate::util::storage_flags::StorageFlags;
9use crate::util::type_constants::{
10 DEFAULT_HASH_SIZE_U16, DEFAULT_HASH_SIZE_U8, U32_SIZE_U16, U32_SIZE_U8, U64_SIZE_U16,
11 U64_SIZE_U8,
12};
13use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
14use dpp::data_contract::document_type::methods::DocumentTypeBasicMethods;
15use dpp::data_contract::document_type::{DocumentPropertyType, DocumentTypeRef, IndexLevel};
16use dpp::document::document_methods::DocumentMethodsV0;
17use dpp::document::{Document, DocumentV0Getters};
18use dpp::version::PlatformVersion;
19use grovedb::batch::key_info::KeyInfo;
20use std::borrow::Cow;
21
22#[derive(Clone, Debug)]
24pub enum DocumentInfo<'a> {
25 DocumentOwnedInfo((Document, Option<Cow<'a, StorageFlags>>)),
27 DocumentRefInfo((&'a Document, Option<Cow<'a, StorageFlags>>)),
29 DocumentRefAndSerialization((&'a Document, &'a [u8], Option<Cow<'a, StorageFlags>>)),
31 DocumentAndSerialization((Document, Vec<u8>, Option<Cow<'a, StorageFlags>>)),
33 DocumentEstimatedAverageSize(u32),
35}
36
37pub trait DocumentInfoV0Methods {
39 fn is_document_and_serialization(&self) -> bool;
41 fn is_document_size(&self) -> bool;
43 fn get_borrowed_document(&self) -> Option<&Document>;
45 fn id_key_value_info(&self) -> KeyValueInfo<'_>;
47 fn get_estimated_size_for_document_type(
49 &self,
50 key_path: &str,
51 document_type: DocumentTypeRef,
52 platform_version: &PlatformVersion,
53 ) -> Result<u16, Error>;
54 fn get_raw_for_document_type(
56 &self,
57 key_path: &str,
58 document_type: DocumentTypeRef,
59 owner_id: Option<[u8; 32]>,
60 size_info_with_base_event: Option<(&IndexLevel, [u8; 32])>,
61 platform_version: &PlatformVersion,
62 ) -> Result<Option<DriveKeyInfo<'_>>, Error>;
63 fn get_raw_array_elements_for_document_type(
68 &self,
69 key_path: &str,
70 document_type: DocumentTypeRef,
71 size_info_with_base_event: Option<(&IndexLevel, [u8; 32])>,
72 platform_version: &PlatformVersion,
73 ) -> Result<Vec<DriveKeyInfo<'_>>, Error>;
74 fn get_borrowed_document_and_storage_flags(&self)
76 -> Option<(&Document, Option<&StorageFlags>)>;
77 fn get_storage_flags_ref(&self) -> Option<&StorageFlags>;
79 fn get_document_id_as_slice(&self) -> Option<&[u8]>;
81}
82
83fn indexed_property_type<'a>(
88 document_type: &'a DocumentTypeRef<'a>,
89 key_path: &str,
90) -> Option<&'a DocumentPropertyType> {
91 match document_type.flattened_properties().get(key_path) {
92 Some(property) => match &property.property_type {
93 DocumentPropertyType::TypedArray(typed_array) => Some(typed_array.item_type.as_ref()),
94 property_type => Some(property_type),
95 },
96 None => document_type.derived_index_property_type(key_path),
97 }
98}
99
100impl DocumentInfo<'_> {
101 pub fn without_storage_flags(self) -> Self {
105 match self {
106 DocumentInfo::DocumentOwnedInfo((document, _)) => {
107 DocumentInfo::DocumentOwnedInfo((document, None))
108 }
109 DocumentInfo::DocumentRefInfo((document, _)) => {
110 DocumentInfo::DocumentRefInfo((document, None))
111 }
112 DocumentInfo::DocumentRefAndSerialization((document, serialization, _)) => {
113 DocumentInfo::DocumentRefAndSerialization((document, serialization, None))
114 }
115 DocumentInfo::DocumentAndSerialization((document, serialization, _)) => {
116 DocumentInfo::DocumentAndSerialization((document, serialization, None))
117 }
118 DocumentInfo::DocumentEstimatedAverageSize(size) => {
119 DocumentInfo::DocumentEstimatedAverageSize(size)
120 }
121 }
122 }
123}
124
125impl DocumentInfoV0Methods for DocumentInfo<'_> {
126 fn is_document_and_serialization(&self) -> bool {
128 matches!(self, DocumentInfo::DocumentRefAndSerialization(..))
129 }
130
131 fn is_document_size(&self) -> bool {
133 matches!(self, DocumentInfo::DocumentEstimatedAverageSize(_))
134 }
135
136 fn get_borrowed_document(&self) -> Option<&Document> {
138 match self {
139 DocumentInfo::DocumentRefAndSerialization((document, _, _))
140 | DocumentInfo::DocumentRefInfo((document, _)) => Some(document),
141 DocumentInfo::DocumentOwnedInfo((document, _))
142 | DocumentInfo::DocumentAndSerialization((document, _, _)) => Some(document),
143 DocumentInfo::DocumentEstimatedAverageSize(_) => None,
144 }
145 }
146
147 fn id_key_value_info(&self) -> KeyValueInfo<'_> {
149 match self {
150 DocumentInfo::DocumentRefAndSerialization((document, _, _))
151 | DocumentInfo::DocumentRefInfo((document, _)) => {
152 KeyRefRequest(document.id_ref().as_slice())
153 }
154 DocumentInfo::DocumentOwnedInfo((document, _))
155 | DocumentInfo::DocumentAndSerialization((document, _, _)) => {
156 KeyRefRequest(document.id_ref().as_slice())
157 }
158 DocumentInfo::DocumentEstimatedAverageSize(document_max_size) => {
159 KeyValueMaxSize((32, *document_max_size))
160 }
161 }
162 }
163
164 fn get_estimated_size_for_document_type(
166 &self,
167 key_path: &str,
168 document_type: DocumentTypeRef,
169 platform_version: &PlatformVersion,
170 ) -> Result<u16, Error> {
171 match key_path {
172 "$ownerId" | "$id" | "$creatorId" | "$moderatedBy" => Ok(DEFAULT_HASH_SIZE_U16),
173 "$createdAt" | "$updatedAt" | "$transferredAt" | "$moderatedAt" => Ok(U64_SIZE_U16),
174 "$createdAtBlockHeight" | "$updatedAtBlockHeight" | "$transferredAtBlockHeight" => {
175 Ok(U64_SIZE_U16)
176 }
177 "$createdAtCoreBlockHeight"
178 | "$updatedAtCoreBlockHeight"
179 | "$transferredAtCoreBlockHeight" => Ok(U32_SIZE_U16),
180 key_path => {
181 let property_type = indexed_property_type(&document_type, key_path).ok_or({
182 Error::Fee(FeeError::DocumentTypeFieldNotFoundForEstimation(format!(
183 "incorrect key path [{}] for document type for estimated sizes",
184 key_path
185 )))
186 })?;
187 let estimated_size = property_type
188 .middle_byte_size_ceil(platform_version)?
189 .ok_or({
190 Error::Drive(DriveError::CorruptedCodeExecution(
191 "document type must have a max size",
192 ))
193 })?;
194 Ok(estimated_size)
195 }
196 }
197 }
198
199 fn get_raw_for_document_type(
201 &self,
202 key_path: &str,
203 document_type: DocumentTypeRef,
204 owner_id: Option<[u8; 32]>,
205 size_info_with_base_event: Option<(&IndexLevel, [u8; 32])>,
206 platform_version: &PlatformVersion,
207 ) -> Result<Option<DriveKeyInfo<'_>>, Error> {
208 match self {
209 DocumentInfo::DocumentRefAndSerialization((document, _, _))
210 | DocumentInfo::DocumentRefInfo((document, _)) => {
211 let raw_value = document.get_raw_for_document_type(
212 key_path,
213 document_type,
214 owner_id,
215 platform_version,
216 )?;
217 match raw_value {
218 None => Ok(None),
219 Some(value) => Ok(Some(Key(value))),
220 }
221 }
222 DocumentInfo::DocumentOwnedInfo((document, _))
223 | DocumentInfo::DocumentAndSerialization((document, _, _)) => {
224 let raw_value = document.get_raw_for_document_type(
225 key_path,
226 document_type,
227 owner_id,
228 platform_version,
229 )?;
230 match raw_value {
231 None => Ok(None),
232 Some(value) => Ok(Some(Key(value))),
233 }
234 }
235 DocumentInfo::DocumentEstimatedAverageSize(_) => {
236 let (index_level, base_event) = size_info_with_base_event.ok_or(Error::Drive(
237 DriveError::CorruptedCodeExecution("size_info_with_base_event None but needed"),
238 ))?;
239 match key_path {
240 "$ownerId" | "$id" | "$creatorId" | "$moderatedBy" => {
241 Ok(Some(KeySize(KeyInfo::MaxKeySize {
242 unique_id: document_type
243 .unique_id_for_document_field(index_level, base_event)
244 .to_vec(),
245 max_size: DEFAULT_HASH_SIZE_U8,
246 })))
247 }
248 "$createdAt" | "$updatedAt" | "$transferredAt" | "$moderatedAt" => {
249 Ok(Some(KeySize(KeyInfo::MaxKeySize {
250 unique_id: document_type
251 .unique_id_for_document_field(index_level, base_event)
252 .to_vec(),
253 max_size: U64_SIZE_U8,
254 })))
255 }
256 "$createdAtBlockHeight"
257 | "$updatedAtBlockHeight"
258 | "$transferredAtBlockHeight" => Ok(Some(KeySize(KeyInfo::MaxKeySize {
259 unique_id: document_type
260 .unique_id_for_document_field(index_level, base_event)
261 .to_vec(),
262 max_size: U64_SIZE_U8,
263 }))),
264 "$createdAtCoreBlockHeight"
265 | "$updatedAtCoreBlockHeight"
266 | "$transferredAtCoreBlockHeight" => Ok(Some(KeySize(KeyInfo::MaxKeySize {
267 unique_id: document_type
268 .unique_id_for_document_field(index_level, base_event)
269 .to_vec(),
270 max_size: U32_SIZE_U8,
271 }))),
272 key_path => {
273 let property_type = indexed_property_type(&document_type, key_path)
274 .ok_or({
275 Error::Fee(FeeError::DocumentTypeFieldNotFoundForEstimation(
276 format!("incorrect key path [{}] for document type for get_raw_for_document_type", key_path)
277 ))
278 })?;
279
280 let estimated_middle_size = property_type
281 .middle_byte_size_ceil(platform_version)?
282 .ok_or({
283 Error::Drive(DriveError::CorruptedCodeExecution(
284 "document type must have a max size",
285 ))
286 })?;
287 if estimated_middle_size > u8::MAX as u16 {
288 return Err(Error::Drive(DriveError::CorruptedCodeExecution(
290 "estimated middle size is too big for a key",
291 )));
292 }
293 Ok(Some(KeySize(KeyInfo::MaxKeySize {
294 unique_id: document_type
295 .unique_id_for_document_field(index_level, base_event)
296 .to_vec(),
297 max_size: estimated_middle_size as u8,
298 })))
299 }
300 }
301 }
302 }
303 }
304
305 fn get_raw_array_elements_for_document_type(
306 &self,
307 key_path: &str,
308 document_type: DocumentTypeRef,
309 size_info_with_base_event: Option<(&IndexLevel, [u8; 32])>,
310 platform_version: &PlatformVersion,
311 ) -> Result<Vec<DriveKeyInfo<'_>>, Error> {
312 if let Some(document) = self.get_borrowed_document() {
313 return Ok(document
314 .get_raw_array_elements_for_document_type(
315 key_path,
316 document_type,
317 platform_version,
318 )?
319 .into_iter()
320 .map(Key)
321 .collect());
322 }
323 let (index_level, _) = size_info_with_base_event.ok_or(Error::Drive(
327 DriveError::CorruptedCodeExecution("size_info_with_base_event None but needed"),
328 ))?;
329 let max_items = index_level.indexed_array_max_items().ok_or(Error::Fee(
330 FeeError::DocumentTypeFieldNotFoundForEstimation(format!(
331 "key path [{}] does not reach a level of typed array elements",
332 key_path
333 )),
334 ))?;
335 match self.get_raw_for_document_type(
336 key_path,
337 document_type,
338 None,
339 size_info_with_base_event,
340 platform_version,
341 )? {
342 Some(KeySize(key_info)) => {
343 Ok(distinct_estimated_keys(&key_info, usize::from(max_items)))
344 }
345 _ => Err(Error::Drive(DriveError::CorruptedCodeExecution(
346 "an estimated document estimates its keys",
347 ))),
348 }
349 }
350
351 fn get_borrowed_document_and_storage_flags(
353 &self,
354 ) -> Option<(&Document, Option<&StorageFlags>)> {
355 match self {
356 DocumentInfo::DocumentRefAndSerialization((document, _, storage_flags))
357 | DocumentInfo::DocumentRefInfo((document, storage_flags)) => {
358 Some((document, storage_flags.as_ref().map(|flags| flags.as_ref())))
359 }
360 DocumentInfo::DocumentOwnedInfo((document, storage_flags))
361 | DocumentInfo::DocumentAndSerialization((document, _, storage_flags)) => {
362 Some((document, storage_flags.as_ref().map(|flags| flags.as_ref())))
363 }
364 DocumentInfo::DocumentEstimatedAverageSize(_) => None,
365 }
366 }
367
368 fn get_storage_flags_ref(&self) -> Option<&StorageFlags> {
370 match self {
371 DocumentInfo::DocumentRefAndSerialization((_, _, storage_flags))
372 | DocumentInfo::DocumentRefInfo((_, storage_flags))
373 | DocumentInfo::DocumentOwnedInfo((_, storage_flags))
374 | DocumentInfo::DocumentAndSerialization((_, _, storage_flags)) => {
375 storage_flags.as_ref().map(|flags| flags.as_ref())
376 }
377 DocumentInfo::DocumentEstimatedAverageSize(_) => {
378 StorageFlags::optional_default_as_ref()
379 }
380 }
381 }
382
383 fn get_document_id_as_slice(&self) -> Option<&[u8]> {
385 match self {
386 DocumentInfo::DocumentRefAndSerialization((document, _, _))
387 | DocumentInfo::DocumentRefInfo((document, _)) => Some(document.id_ref().as_slice()),
388 DocumentInfo::DocumentOwnedInfo((document, _))
389 | DocumentInfo::DocumentAndSerialization((document, _, _)) => {
390 Some(document.id_ref().as_slice())
391 }
392 DocumentInfo::DocumentEstimatedAverageSize(_) => None,
393 }
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400 use dpp::document::DocumentV0;
401 use dpp::prelude::Identifier;
402 use std::collections::BTreeMap;
403
404 fn make_document(id_bytes: [u8; 32]) -> Document {
406 Document::V0(DocumentV0 {
407 contract_version: None,
408 id: Identifier::new(id_bytes),
409 owner_id: Identifier::new([0xAA; 32]),
410 properties: BTreeMap::new(),
411 revision: Some(1),
412 created_at: None,
413 updated_at: None,
414 transferred_at: None,
415 created_at_block_height: None,
416 updated_at_block_height: None,
417 transferred_at_block_height: None,
418 created_at_core_block_height: None,
419 updated_at_core_block_height: None,
420 transferred_at_core_block_height: None,
421 creator_id: None,
422 moderated_at: None,
423 moderated_by: None,
424 })
425 }
426
427 #[test]
432 fn test_is_document_and_serialization_true_for_ref_and_serialization() {
433 let doc = make_document([1; 32]);
434 let serialized = vec![1, 2, 3];
435 let info = DocumentInfo::DocumentRefAndSerialization((&doc, &serialized, None));
436 assert!(info.is_document_and_serialization());
437 }
438
439 #[test]
440 fn test_is_document_and_serialization_false_for_owned_info() {
441 let doc = make_document([2; 32]);
442 let info = DocumentInfo::DocumentOwnedInfo((doc, None));
443 assert!(!info.is_document_and_serialization());
444 }
445
446 #[test]
447 fn test_is_document_and_serialization_false_for_ref_info() {
448 let doc = make_document([3; 32]);
449 let info = DocumentInfo::DocumentRefInfo((&doc, None));
450 assert!(!info.is_document_and_serialization());
451 }
452
453 #[test]
454 fn test_is_document_and_serialization_false_for_estimated_size() {
455 let info = DocumentInfo::DocumentEstimatedAverageSize(100);
456 assert!(!info.is_document_and_serialization());
457 }
458
459 #[test]
460 fn test_is_document_and_serialization_false_for_document_and_serialization() {
461 let doc = make_document([4; 32]);
462 let info = DocumentInfo::DocumentAndSerialization((doc, vec![9, 8, 7], None));
463 assert!(!info.is_document_and_serialization());
464 }
465
466 #[test]
471 fn test_is_document_size_true_for_estimated() {
472 let info = DocumentInfo::DocumentEstimatedAverageSize(256);
473 assert!(info.is_document_size());
474 }
475
476 #[test]
477 fn test_is_document_size_false_for_owned_info() {
478 let doc = make_document([5; 32]);
479 let info = DocumentInfo::DocumentOwnedInfo((doc, None));
480 assert!(!info.is_document_size());
481 }
482
483 #[test]
484 fn test_is_document_size_false_for_ref_info() {
485 let doc = make_document([6; 32]);
486 let info = DocumentInfo::DocumentRefInfo((&doc, None));
487 assert!(!info.is_document_size());
488 }
489
490 #[test]
495 fn test_get_borrowed_document_from_ref_info() {
496 let doc = make_document([10; 32]);
497 let info = DocumentInfo::DocumentRefInfo((&doc, None));
498 let borrowed = info.get_borrowed_document();
499 assert!(borrowed.is_some());
500 assert_eq!(borrowed.unwrap().id_ref().as_slice(), &[10u8; 32]);
501 }
502
503 #[test]
504 fn test_get_borrowed_document_from_ref_and_serialization() {
505 let doc = make_document([11; 32]);
506 let ser = vec![0u8; 5];
507 let info = DocumentInfo::DocumentRefAndSerialization((&doc, &ser, None));
508 let borrowed = info.get_borrowed_document();
509 assert!(borrowed.is_some());
510 assert_eq!(borrowed.unwrap().id_ref().as_slice(), &[11u8; 32]);
511 }
512
513 #[test]
514 fn test_get_borrowed_document_from_owned_info() {
515 let doc = make_document([12; 32]);
516 let info = DocumentInfo::DocumentOwnedInfo((doc, None));
517 let borrowed = info.get_borrowed_document();
518 assert!(borrowed.is_some());
519 assert_eq!(borrowed.unwrap().id_ref().as_slice(), &[12u8; 32]);
520 }
521
522 #[test]
523 fn test_get_borrowed_document_from_document_and_serialization() {
524 let doc = make_document([13; 32]);
525 let info = DocumentInfo::DocumentAndSerialization((doc, vec![1, 2], None));
526 let borrowed = info.get_borrowed_document();
527 assert!(borrowed.is_some());
528 assert_eq!(borrowed.unwrap().id_ref().as_slice(), &[13u8; 32]);
529 }
530
531 #[test]
532 fn test_get_borrowed_document_none_for_estimated() {
533 let info = DocumentInfo::DocumentEstimatedAverageSize(500);
534 assert!(info.get_borrowed_document().is_none());
535 }
536
537 #[test]
542 fn test_id_key_value_info_ref_info_returns_key_ref_request() {
543 let doc = make_document([20; 32]);
544 let info = DocumentInfo::DocumentRefInfo((&doc, None));
545 match info.id_key_value_info() {
546 KeyRefRequest(key) => {
547 assert_eq!(key, &[20u8; 32]);
548 }
549 _ => panic!("expected KeyRefRequest"),
550 }
551 }
552
553 #[test]
554 fn test_id_key_value_info_owned_info_returns_key_ref_request() {
555 let doc = make_document([21; 32]);
556 let info = DocumentInfo::DocumentOwnedInfo((doc, None));
557 match info.id_key_value_info() {
558 KeyRefRequest(key) => {
559 assert_eq!(key, &[21u8; 32]);
560 }
561 _ => panic!("expected KeyRefRequest"),
562 }
563 }
564
565 #[test]
566 fn test_id_key_value_info_estimated_returns_key_value_max_size() {
567 let info = DocumentInfo::DocumentEstimatedAverageSize(999);
568 match info.id_key_value_info() {
569 KeyValueMaxSize((key_size, doc_size)) => {
570 assert_eq!(key_size, 32);
571 assert_eq!(doc_size, 999);
572 }
573 _ => panic!("expected KeyValueMaxSize"),
574 }
575 }
576
577 #[test]
578 fn test_id_key_value_info_ref_and_serialization_returns_key_ref_request() {
579 let doc = make_document([22; 32]);
580 let ser = vec![0u8; 3];
581 let info = DocumentInfo::DocumentRefAndSerialization((&doc, &ser, None));
582 match info.id_key_value_info() {
583 KeyRefRequest(key) => {
584 assert_eq!(key, &[22u8; 32]);
585 }
586 _ => panic!("expected KeyRefRequest"),
587 }
588 }
589
590 #[test]
591 fn test_id_key_value_info_document_and_serialization_returns_key_ref_request() {
592 let doc = make_document([23; 32]);
593 let info = DocumentInfo::DocumentAndSerialization((doc, vec![5, 6, 7], None));
594 match info.id_key_value_info() {
595 KeyRefRequest(key) => {
596 assert_eq!(key, &[23u8; 32]);
597 }
598 _ => panic!("expected KeyRefRequest"),
599 }
600 }
601
602 #[test]
607 fn test_estimated_size_for_owner_id() {
608 let info = DocumentInfo::DocumentEstimatedAverageSize(100);
609 assert_eq!(DEFAULT_HASH_SIZE_U16, 32);
625 assert_eq!(U64_SIZE_U16, 8);
626 assert_eq!(U32_SIZE_U16, 4);
627 drop(info);
630 }
631
632 #[test]
637 fn test_get_borrowed_document_and_storage_flags_from_ref_info_no_flags() {
638 let doc = make_document([30; 32]);
639 let info = DocumentInfo::DocumentRefInfo((&doc, None));
640 let result = info.get_borrowed_document_and_storage_flags();
641 assert!(result.is_some());
642 let (d, flags) = result.unwrap();
643 assert_eq!(d.id_ref().as_slice(), &[30u8; 32]);
644 assert!(flags.is_none());
645 }
646
647 #[test]
648 fn test_get_borrowed_document_and_storage_flags_from_owned_info_no_flags() {
649 let doc = make_document([31; 32]);
650 let info = DocumentInfo::DocumentOwnedInfo((doc, None));
651 let result = info.get_borrowed_document_and_storage_flags();
652 assert!(result.is_some());
653 let (d, flags) = result.unwrap();
654 assert_eq!(d.id_ref().as_slice(), &[31u8; 32]);
655 assert!(flags.is_none());
656 }
657
658 #[test]
659 fn test_get_borrowed_document_and_storage_flags_none_for_estimated() {
660 let info = DocumentInfo::DocumentEstimatedAverageSize(200);
661 assert!(info.get_borrowed_document_and_storage_flags().is_none());
662 }
663
664 #[test]
665 fn test_get_borrowed_document_and_storage_flags_ref_and_serialization() {
666 let doc = make_document([32; 32]);
667 let ser = vec![7u8; 4];
668 let info = DocumentInfo::DocumentRefAndSerialization((&doc, &ser, None));
669 let result = info.get_borrowed_document_and_storage_flags();
670 assert!(result.is_some());
671 let (d, flags) = result.unwrap();
672 assert_eq!(d.id_ref().as_slice(), &[32u8; 32]);
673 assert!(flags.is_none());
674 }
675
676 #[test]
677 fn test_get_borrowed_document_and_storage_flags_document_and_serialization() {
678 let doc = make_document([33; 32]);
679 let info = DocumentInfo::DocumentAndSerialization((doc, vec![10, 20], None));
680 let result = info.get_borrowed_document_and_storage_flags();
681 assert!(result.is_some());
682 let (d, flags) = result.unwrap();
683 assert_eq!(d.id_ref().as_slice(), &[33u8; 32]);
684 assert!(flags.is_none());
685 }
686
687 #[test]
692 fn test_get_storage_flags_ref_none_without_flags() {
693 let doc = make_document([40; 32]);
694 let info = DocumentInfo::DocumentRefInfo((&doc, None));
695 assert!(info.get_storage_flags_ref().is_none());
696 }
697
698 #[test]
699 fn test_get_storage_flags_ref_none_for_owned_without_flags() {
700 let doc = make_document([41; 32]);
701 let info = DocumentInfo::DocumentOwnedInfo((doc, None));
702 assert!(info.get_storage_flags_ref().is_none());
703 }
704
705 #[test]
710 fn test_get_document_id_as_slice_from_ref_info() {
711 let doc = make_document([50; 32]);
712 let info = DocumentInfo::DocumentRefInfo((&doc, None));
713 assert_eq!(info.get_document_id_as_slice(), Some([50u8; 32].as_slice()));
714 }
715
716 #[test]
717 fn test_get_document_id_as_slice_from_owned_info() {
718 let doc = make_document([51; 32]);
719 let info = DocumentInfo::DocumentOwnedInfo((doc, None));
720 assert_eq!(info.get_document_id_as_slice(), Some([51u8; 32].as_slice()));
721 }
722
723 #[test]
724 fn test_get_document_id_as_slice_from_ref_and_serialization() {
725 let doc = make_document([52; 32]);
726 let ser = vec![0u8; 2];
727 let info = DocumentInfo::DocumentRefAndSerialization((&doc, &ser, None));
728 assert_eq!(info.get_document_id_as_slice(), Some([52u8; 32].as_slice()));
729 }
730
731 #[test]
732 fn test_get_document_id_as_slice_from_document_and_serialization() {
733 let doc = make_document([53; 32]);
734 let info = DocumentInfo::DocumentAndSerialization((doc, vec![3, 4], None));
735 assert_eq!(info.get_document_id_as_slice(), Some([53u8; 32].as_slice()));
736 }
737
738 #[test]
739 fn test_get_document_id_as_slice_none_for_estimated() {
740 let info = DocumentInfo::DocumentEstimatedAverageSize(100);
741 assert!(info.get_document_id_as_slice().is_none());
742 }
743
744 #[test]
749 fn test_estimated_average_size_clone_preserves_value() {
750 let info = DocumentInfo::DocumentEstimatedAverageSize(42);
751 let cloned = info.clone();
752 match cloned {
753 DocumentInfo::DocumentEstimatedAverageSize(v) => assert_eq!(v, 42),
754 _ => panic!("clone should preserve variant"),
755 }
756 }
757}