firestore_path/document_name.rs
1use std::str::FromStr;
2
3use crate::{
4 error::ErrorKind, CollectionId, CollectionName, CollectionPath, DatabaseName, DocumentId,
5 DocumentPath, Error, RootDocumentName,
6};
7
8/// A document name.
9///
10/// # Format
11///
12/// `{database_name}/{document_path}`
13///
14/// # Examples
15///
16/// ```rust
17/// # fn main() -> anyhow::Result<()> {
18/// use firestore_path::DocumentName;
19/// # use firestore_path::{CollectionId,CollectionName,DatabaseName,DocumentId,DocumentPath};
20/// # use std::str::FromStr;
21///
22/// let document_name = DocumentName::from_str(
23/// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
24/// )?;
25/// assert_eq!(
26/// document_name.to_string(),
27/// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
28/// );
29///
30/// assert_eq!(
31/// document_name.clone().collection("messages")?,
32/// CollectionName::from_str(
33/// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages"
34/// )?
35/// );
36/// assert_eq!(document_name.collection_id(), &CollectionId::from_str("chatrooms")?);
37/// assert_eq!(
38/// document_name.database_name(),
39/// &DatabaseName::from_str("projects/my-project/databases/my-database")?
40/// );
41/// assert_eq!(document_name.document_id(), &DocumentId::from_str("chatroom1")?);
42/// assert_eq!(document_name.document_path(), &DocumentPath::from_str("chatrooms/chatroom1")?);
43/// assert_eq!(
44/// document_name.clone().parent(),
45/// CollectionName::from_str("projects/my-project/databases/my-database/documents/chatrooms")?
46/// );
47///
48/// assert_eq!(
49/// DocumentPath::from(document_name.clone()),
50/// DocumentPath::from_str("chatrooms/chatroom1")?
51/// );
52///
53/// # Ok(())
54/// # }
55/// ```
56///
57#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
58pub struct DocumentName {
59 document_path: DocumentPath,
60 root_document_name: RootDocumentName,
61}
62
63impl DocumentName {
64 /// Creates a new `DocumentName`.
65 ///
66 /// # Examples
67 ///
68 /// ```rust
69 /// # fn main() -> anyhow::Result<()> {
70 /// use firestore_path::{DatabaseName,DocumentName,DocumentPath,RootDocumentName};
71 /// use std::str::FromStr;
72 ///
73 /// let root_document_name = RootDocumentName::from_str("projects/my-project/databases/my-database/documents")?;
74 /// let document_path = DocumentPath::from_str("chatrooms/chatroom1")?;
75 /// let document_name = DocumentName::new(root_document_name, document_path);
76 /// assert_eq!(
77 /// document_name.to_string(),
78 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
79 /// );
80 ///
81 /// let database_name = DatabaseName::from_str("projects/my-project/databases/my-database")?;
82 /// let document_path = DocumentPath::from_str("chatrooms/chatroom1")?;
83 /// let document_name = DocumentName::new(database_name, document_path);
84 /// assert_eq!(
85 /// document_name.to_string(),
86 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
87 /// );
88 /// # Ok(())
89 /// # }
90 /// ```
91 ///
92 pub fn new<D>(root_document_name: D, document_path: DocumentPath) -> Self
93 where
94 D: Into<RootDocumentName>,
95 {
96 Self {
97 document_path,
98 root_document_name: root_document_name.into(),
99 }
100 }
101
102 /// Creates a new `CollectionName` from this `DocumentName` and `collection_path`.
103 ///
104 /// # Examples
105 ///
106 /// ```rust
107 /// # fn main() -> anyhow::Result<()> {
108 /// use firestore_path::{CollectionId,CollectionName,CollectionPath,DocumentName};
109 /// use std::str::FromStr;
110 ///
111 /// let document_name = DocumentName::from_str(
112 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
113 /// )?;
114 /// assert_eq!(
115 /// document_name.collection("messages")?,
116 /// CollectionName::from_str(
117 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages"
118 /// )?
119 /// );
120 /// assert_eq!(
121 /// document_name.collection("messages/message1/col")?,
122 /// CollectionName::from_str(
123 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col"
124 /// )?
125 /// );
126 /// assert_eq!(
127 /// document_name.collection(CollectionId::from_str("messages")?)?,
128 /// CollectionName::from_str(
129 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages"
130 /// )?
131 /// );
132 /// assert_eq!(
133 /// document_name.collection(CollectionPath::from_str("messages/message1/col")?)?,
134 /// CollectionName::from_str(
135 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col"
136 /// )?
137 /// );
138 /// # Ok(())
139 /// # }
140 /// ```
141 ///
142 pub fn collection<E, T>(&self, collection_path: T) -> Result<CollectionName, Error>
143 where
144 E: std::fmt::Display,
145 T: TryInto<CollectionPath, Error = E>,
146 {
147 self.clone().into_collection(collection_path)
148 }
149
150 /// Returns the `CollectionId` of this `DocumentName`.
151 ///
152 /// # Examples
153 ///
154 /// ```rust
155 /// # fn main() -> anyhow::Result<()> {
156 /// use firestore_path::{CollectionId,DocumentName};
157 /// use std::str::FromStr;
158 ///
159 /// let document_name = DocumentName::from_str(
160 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
161 /// )?;
162 /// assert_eq!(
163 /// document_name.collection_id(),
164 /// &CollectionId::from_str("chatrooms")?
165 /// );
166 /// # Ok(())
167 /// # }
168 /// ```
169 pub fn collection_id(&self) -> &CollectionId {
170 self.document_path.collection_id()
171 }
172
173 /// Returns the `DatabaseName` of this `DocumentName`.
174 ///
175 /// # Examples
176 ///
177 /// ```rust
178 /// # fn main() -> anyhow::Result<()> {
179 /// use firestore_path::{DatabaseName,DocumentName,DocumentPath};
180 /// use std::str::FromStr;
181 ///
182 /// let document_name = DocumentName::from_str(
183 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
184 /// )?;
185 /// assert_eq!(
186 /// document_name.database_name(),
187 /// &DatabaseName::from_str("projects/my-project/databases/my-database")?
188 /// );
189 /// # Ok(())
190 /// # }
191 /// ```
192 ///
193 pub fn database_name(&self) -> &DatabaseName {
194 self.root_document_name.as_database_name()
195 }
196
197 /// Creates a new `DocumentName` from this `DocumentName` and `document_path`.
198 ///
199 /// # Examples
200 ///
201 /// ```rust
202 /// # fn main() -> anyhow::Result<()> {
203 /// use firestore_path::{CollectionPath,DocumentName,DocumentPath};
204 /// use std::str::FromStr;
205 ///
206 /// let document_name = DocumentName::from_str(
207 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
208 /// )?;
209 /// assert_eq!(
210 /// document_name.doc("messages/message1")?,
211 /// DocumentName::from_str(
212 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1"
213 /// )?
214 /// );
215 /// assert_eq!(
216 /// document_name.doc("messages/message1/col/doc")?,
217 /// DocumentName::from_str(
218 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col/doc"
219 /// )?
220 /// );
221 /// assert_eq!(
222 /// document_name.doc(DocumentPath::from_str("messages/message1")?)?,
223 /// DocumentName::from_str(
224 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1"
225 /// )?
226 /// );
227 /// assert_eq!(
228 /// document_name.doc(DocumentPath::from_str("messages/message1/col/doc")?)?,
229 /// DocumentName::from_str(
230 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col/doc"
231 /// )?
232 /// );
233 /// # Ok(())
234 /// # }
235 /// ```
236 ///
237 pub fn doc<E, T>(&self, document_path: T) -> Result<DocumentName, Error>
238 where
239 E: std::fmt::Display,
240 T: TryInto<DocumentPath, Error = E>,
241 {
242 self.clone().into_doc(document_path)
243 }
244
245 /// Returns the `DocumentId` of this `DocumentName`.
246 ///
247 /// # Examples
248 ///
249 /// ```rust
250 /// # fn main() -> anyhow::Result<()> {
251 /// use firestore_path::{DocumentId,DocumentName};
252 /// use std::str::FromStr;
253 ///
254 /// let document_name = DocumentName::from_str(
255 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
256 /// )?;
257 /// assert_eq!(document_name.document_id(), &DocumentId::from_str("chatroom1")?);
258 /// # Ok(())
259 /// # }
260 /// ```
261 ///
262 pub fn document_id(&self) -> &DocumentId {
263 self.document_path.document_id()
264 }
265
266 /// Returns the `DocumentPath` of this `DocumentName`.
267 ///
268 /// # Examples
269 ///
270 /// ```rust
271 /// # fn main() -> anyhow::Result<()> {
272 /// use firestore_path::{DocumentName,DocumentPath};
273 /// use std::str::FromStr;
274 ///
275 /// let document_name = DocumentName::from_str(
276 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
277 /// )?;
278 /// assert_eq!(
279 /// document_name.document_path(),
280 /// &DocumentPath::from_str("chatrooms/chatroom1")?
281 /// );
282 /// # Ok(())
283 /// # }
284 /// ```
285 ///
286 pub fn document_path(&self) -> &DocumentPath {
287 &self.document_path
288 }
289
290 /// Creates a new `CollectionName` from this `DocumentName` and `collection_path`.
291 ///
292 /// # Examples
293 ///
294 /// ```rust
295 /// # fn main() -> anyhow::Result<()> {
296 /// use firestore_path::{CollectionId,CollectionName,CollectionPath,DocumentName};
297 /// use std::str::FromStr;
298 ///
299 /// let document_name = DocumentName::from_str(
300 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
301 /// )?;
302 /// assert_eq!(
303 /// document_name.clone().into_collection("messages")?,
304 /// CollectionName::from_str(
305 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages"
306 /// )?
307 /// );
308 /// assert_eq!(
309 /// document_name.clone().into_collection("messages/message1/col")?,
310 /// CollectionName::from_str(
311 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col"
312 /// )?
313 /// );
314 /// assert_eq!(
315 /// document_name.clone().into_collection(CollectionId::from_str("messages")?)?,
316 /// CollectionName::from_str(
317 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages"
318 /// )?
319 /// );
320 /// assert_eq!(
321 /// document_name.into_collection(CollectionPath::from_str("messages/message1/col")?)?,
322 /// CollectionName::from_str(
323 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col"
324 /// )?
325 /// );
326 /// # Ok(())
327 /// # }
328 /// ```
329 ///
330 pub fn into_collection<E, T>(self, collection_path: T) -> Result<CollectionName, Error>
331 where
332 E: std::fmt::Display,
333 T: TryInto<CollectionPath, Error = E>,
334 {
335 Ok(CollectionName::new(
336 self.root_document_name,
337 self.document_path.into_collection(collection_path)?,
338 ))
339 }
340
341 /// Creates a new `DocumentName` by consuming the `DocumentName` with the provided `document_path`.
342 ///
343 /// # Examples
344 ///
345 /// ```rust
346 /// # fn main() -> anyhow::Result<()> {
347 /// use firestore_path::{CollectionPath,DocumentName,DocumentPath};
348 /// use std::str::FromStr;
349 ///
350 /// let document_name = DocumentName::from_str(
351 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
352 /// )?;
353 /// assert_eq!(
354 /// document_name.clone().into_doc("messages/message1")?,
355 /// DocumentName::from_str(
356 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1"
357 /// )?
358 /// );
359 /// assert_eq!(
360 /// document_name.clone().into_doc("messages/message1/col/doc")?,
361 /// DocumentName::from_str(
362 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col/doc"
363 /// )?
364 /// );
365 /// assert_eq!(
366 /// document_name.clone().into_doc(DocumentPath::from_str("messages/message1")?)?,
367 /// DocumentName::from_str(
368 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1"
369 /// )?
370 /// );
371 /// assert_eq!(
372 /// document_name.into_doc(DocumentPath::from_str("messages/message1/col/doc")?)?,
373 /// DocumentName::from_str(
374 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col/doc"
375 /// )?
376 /// );
377 /// # Ok(())
378 /// # }
379 /// ```
380 ///
381 pub fn into_doc<E, T>(self, document_path: T) -> Result<DocumentName, Error>
382 where
383 E: std::fmt::Display,
384 T: TryInto<DocumentPath, Error = E>,
385 {
386 Ok(DocumentName::new(
387 self.root_document_name,
388 self.document_path.into_doc(document_path)?,
389 ))
390 }
391
392 /// Consumes the `DocumentName`, returning the parent `CollectionName`.
393 ///
394 /// # Examples
395 ///
396 /// ```rust
397 /// # fn main() -> anyhow::Result<()> {
398 /// use firestore_path::{CollectionName,DocumentName};
399 /// use std::str::FromStr;
400 ///
401 /// let document_name = DocumentName::from_str(
402 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
403 /// )?;
404 /// assert_eq!(
405 /// document_name.into_parent(),
406 /// CollectionName::from_str(
407 /// "projects/my-project/databases/my-database/documents/chatrooms"
408 /// )?
409 /// );
410 /// # Ok(())
411 /// # }
412 /// ```
413 ///
414 pub fn into_parent(self) -> CollectionName {
415 CollectionName::new(
416 self.root_document_name,
417 CollectionPath::from(self.document_path),
418 )
419 }
420
421 /// Consumes the `DocumentName`, returning the parent `DocumentName`.
422 ///
423 /// # Examples
424 ///
425 /// ```rust
426 /// # fn main() -> anyhow::Result<()> {
427 /// use firestore_path::{CollectionName,DocumentName};
428 /// use std::str::FromStr;
429 ///
430 /// let document_name = DocumentName::from_str(
431 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
432 /// )?;
433 /// assert_eq!(document_name.into_parent_document_name(), None);
434 /// let document_name = DocumentName::from_str(
435 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1"
436 /// )?;
437 /// assert_eq!(
438 /// document_name.into_parent_document_name(),
439 /// Some(DocumentName::from_str(
440 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
441 /// )?)
442 /// );
443 /// # Ok(())
444 /// # }
445 /// ```
446 pub fn into_parent_document_name(self) -> Option<DocumentName> {
447 self.document_path
448 .into_parent()
449 .into_parent()
450 .map(|document_path| DocumentName::new(self.root_document_name, document_path))
451 }
452
453 /// Consumes the `DocumentName`, returning the `RootDocumentName`.
454 ///
455 /// # Examples
456 ///
457 /// ```rust
458 /// # fn main() -> anyhow::Result<()> {
459 /// use firestore_path::{DocumentName,RootDocumentName};
460 /// use std::str::FromStr;
461 ///
462 /// let document_name = DocumentName::from_str(
463 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
464 /// )?;
465 /// let root_document_name = document_name.into_root_document_name();
466 /// assert_eq!(
467 /// root_document_name,
468 /// RootDocumentName::from_str(
469 /// "projects/my-project/databases/my-database/documents"
470 /// )?
471 /// );
472 /// # Ok(())
473 /// # }
474 pub fn into_root_document_name(self) -> RootDocumentName {
475 self.root_document_name
476 }
477
478 /// Returns the parent `CollectionName` of this `DocumentName`.
479 ///
480 /// # Examples
481 ///
482 /// ```rust
483 /// # fn main() -> anyhow::Result<()> {
484 /// use firestore_path::{CollectionName,DocumentName};
485 /// use std::str::FromStr;
486 ///
487 /// let document_name = DocumentName::from_str(
488 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
489 /// )?;
490 /// assert_eq!(
491 /// document_name.parent(),
492 /// CollectionName::from_str(
493 /// "projects/my-project/databases/my-database/documents/chatrooms"
494 /// )?
495 /// );
496 /// assert_eq!(
497 /// document_name.parent(),
498 /// CollectionName::from_str(
499 /// "projects/my-project/databases/my-database/documents/chatrooms"
500 /// )?
501 /// );
502 /// # Ok(())
503 /// # }
504 /// ```
505 ///
506 pub fn parent(&self) -> CollectionName {
507 self.clone().into_parent()
508 }
509
510 /// Returns the parent `DocumentName` of this `DocumentName`.
511 ///
512 /// # Examples
513 ///
514 /// ```rust
515 /// # fn main() -> anyhow::Result<()> {
516 /// use firestore_path::{CollectionName,DocumentName};
517 /// use std::str::FromStr;
518 ///
519 /// let document_name = DocumentName::from_str(
520 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
521 /// )?;
522 /// assert_eq!(document_name.parent_document_name(), None);
523 /// let document_name = DocumentName::from_str(
524 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1"
525 /// )?;
526 /// assert_eq!(
527 /// document_name.parent_document_name(),
528 /// Some(DocumentName::from_str(
529 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
530 /// )?)
531 /// );
532 /// # Ok(())
533 /// # }
534 /// ```
535 pub fn parent_document_name(&self) -> Option<DocumentName> {
536 self.clone().into_parent_document_name()
537 }
538
539 /// Returns the `RootDocumentName` of this `DocumentName`.
540 ///
541 /// # Examples
542 ///
543 /// ```rust
544 /// # fn main() -> anyhow::Result<()> {
545 /// use firestore_path::{DocumentName,RootDocumentName};
546 /// use std::str::FromStr;
547 ///
548 /// let document_name = DocumentName::from_str(
549 /// "projects/my-project/databases/my-database/documents/chatrooms/chatroom1"
550 /// )?;
551 /// let root_document_name = document_name.root_document_name();
552 /// assert_eq!(
553 /// root_document_name,
554 /// &RootDocumentName::from_str(
555 /// "projects/my-project/databases/my-database/documents"
556 /// )?
557 /// );
558 /// # Ok(())
559 /// # }
560 pub fn root_document_name(&self) -> &RootDocumentName {
561 &self.root_document_name
562 }
563}
564
565impl std::convert::From<DocumentName> for DatabaseName {
566 fn from(document_name: DocumentName) -> Self {
567 Self::from(document_name.root_document_name)
568 }
569}
570
571impl std::convert::From<DocumentName> for DocumentId {
572 fn from(document_name: DocumentName) -> Self {
573 Self::from(document_name.document_path)
574 }
575}
576
577impl std::convert::From<DocumentName> for DocumentPath {
578 fn from(document_name: DocumentName) -> Self {
579 document_name.document_path
580 }
581}
582
583impl std::convert::TryFrom<&str> for DocumentName {
584 type Error = Error;
585
586 fn try_from(s: &str) -> Result<Self, Self::Error> {
587 // <https://firebase.google.com/docs/firestore/quotas#collections_documents_and_fields>
588 if !(1..=6_144).contains(&s.len()) {
589 return Err(Error::from(ErrorKind::LengthOutOfBounds));
590 }
591
592 let parts = s.split('/').collect::<Vec<&str>>();
593 if parts.len() < 5 + 2 || (parts.len() - 5) % 2 != 0 {
594 return Err(Error::from(ErrorKind::InvalidNumberOfPathComponents));
595 }
596
597 Ok(Self {
598 root_document_name: RootDocumentName::from_str(&parts[0..5].join("/"))?,
599 document_path: DocumentPath::from_str(&parts[5..].join("/"))?,
600 })
601 }
602}
603
604impl std::convert::TryFrom<String> for DocumentName {
605 type Error = Error;
606
607 fn try_from(s: String) -> Result<Self, Self::Error> {
608 Self::try_from(s.as_str())
609 }
610}
611
612impl std::fmt::Display for DocumentName {
613 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
614 write!(f, "{}/{}", self.root_document_name, self.document_path)
615 }
616}
617
618impl std::str::FromStr for DocumentName {
619 type Err = Error;
620
621 fn from_str(s: &str) -> Result<Self, Self::Err> {
622 Self::try_from(s)
623 }
624}
625
626#[cfg(test)]
627mod tests {
628 use std::str::FromStr;
629
630 use crate::{CollectionPath, DocumentId};
631
632 use super::*;
633
634 #[test]
635 fn test() -> anyhow::Result<()> {
636 let s = "projects/my-project/databases/my-database/documents/chatrooms/chatroom1";
637 let document_name = DocumentName::from_str(s)?;
638 assert_eq!(document_name.to_string(), s);
639 Ok(())
640 }
641
642 #[test]
643 fn test_collection() -> anyhow::Result<()> {
644 let document_name = DocumentName::from_str(
645 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1",
646 )?;
647 let collection_name = document_name.into_collection("messages")?;
648 assert_eq!(
649 collection_name,
650 CollectionName::from_str(
651 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages"
652 )?
653 );
654
655 let document_name = DocumentName::from_str(
656 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1",
657 )?;
658 let collection_name = document_name.into_collection("col")?;
659 assert_eq!(
660 collection_name,
661 CollectionName::from_str(
662 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col"
663 )?
664 );
665
666 let document_name = DocumentName::from_str(
667 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1",
668 )?;
669 let collection_id = CollectionId::from_str("messages")?;
670 let collection_name = document_name.into_collection(collection_id)?;
671 assert_eq!(
672 collection_name,
673 CollectionName::from_str(
674 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages"
675 )?
676 );
677 Ok(())
678 }
679
680 #[test]
681 fn test_collection_with_colleciton_path() -> anyhow::Result<()> {
682 let document_name = DocumentName::from_str(
683 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1",
684 )?;
685 let collection_name = document_name.into_collection("messages/message1/col")?;
686 assert_eq!(
687 collection_name,
688 CollectionName::from_str(
689 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col"
690 )?
691 );
692
693 let document_name = DocumentName::from_str(
694 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1",
695 )?;
696 let collection_path = CollectionPath::from_str("messages/message1/col")?;
697 let collection_name = document_name.into_collection(collection_path)?;
698 assert_eq!(
699 collection_name,
700 CollectionName::from_str(
701 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1/messages/message1/col"
702 )?
703 );
704 Ok(())
705 }
706
707 #[test]
708 fn test_document_id() -> anyhow::Result<()> {
709 let document_name = DocumentName::from_str(
710 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1",
711 )?;
712 assert_eq!(
713 document_name.document_id(),
714 &DocumentId::from_str("chatroom1")?
715 );
716 Ok(())
717 }
718
719 #[test]
720 fn test_impl_from_database_name_for_document_id() -> anyhow::Result<()> {
721 let document_name = DocumentName::from_str(
722 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1",
723 )?;
724 assert_eq!(
725 DatabaseName::from(document_name),
726 DatabaseName::from_str("projects/my-project/databases/my-database")?
727 );
728 Ok(())
729 }
730
731 #[test]
732 fn test_impl_from_document_name_for_document_id() -> anyhow::Result<()> {
733 let document_name = DocumentName::from_str(
734 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1",
735 )?;
736 assert_eq!(
737 DocumentId::from(document_name),
738 DocumentId::from_str("chatroom1")?
739 );
740 Ok(())
741 }
742
743 #[test]
744 fn test_impl_from_str_and_impl_try_from_string() -> anyhow::Result<()> {
745 let b = "projects/my-project/databases/my-database/documents";
746 let c1 = "x".repeat(1500);
747 let d1 = "x".repeat(1500);
748 let c2 = "y".repeat(1500);
749 let d2 = "y".repeat(1500);
750 let c3 = "z".repeat(80);
751 let d3_ok = "z".repeat(7);
752 let d3_err = "z".repeat(7 + 1);
753 let s1 = format!("{}/{}/{}/{}/{}/{}/{}", b, c1, d1, c2, d2, c3, d3_ok);
754 assert_eq!(s1.len(), 6_144);
755 let s2 = format!("{}/{}/{}/{}/{}/{}/{}", b, c1, d1, c2, d2, c3, d3_err);
756 assert_eq!(s2.len(), 6_145);
757
758 for (s, expected) in [
759 ("projects/my-project/databases/my-database/documents", false),
760 (
761 "projects/my-project/databases/my-database/documents/c",
762 false,
763 ),
764 (
765 "projects/my-project/databases/my-database/documents/c/d",
766 true,
767 ),
768 (
769 "projects/my-project/databases/my-database/documents/c/d/c",
770 false,
771 ),
772 (
773 "projects/my-project/databases/my-database/documents/c/d/c/d",
774 true,
775 ),
776 (s1.as_ref(), true),
777 (s2.as_ref(), false),
778 ] {
779 assert_eq!(DocumentName::from_str(s).is_ok(), expected);
780 assert_eq!(DocumentName::try_from(s).is_ok(), expected);
781 assert_eq!(DocumentName::try_from(s.to_string()).is_ok(), expected);
782 if expected {
783 assert_eq!(DocumentName::from_str(s)?, DocumentName::try_from(s)?);
784 assert_eq!(
785 DocumentName::from_str(s)?,
786 DocumentName::try_from(s.to_string())?
787 );
788 assert_eq!(DocumentName::from_str(s)?.to_string(), s);
789 }
790 }
791 Ok(())
792 }
793
794 #[test]
795 fn test_parent() -> anyhow::Result<()> {
796 let document_name = DocumentName::from_str(
797 "projects/my-project/databases/my-database/documents/chatrooms/chatroom1",
798 )?;
799 assert_eq!(
800 document_name.into_parent(),
801 CollectionName::from_str(
802 "projects/my-project/databases/my-database/documents/chatrooms",
803 )?
804 );
805 Ok(())
806 }
807}