Skip to main content

bible_io/
chapter.rs

1use std::fmt;
2
3use crate::verse::Verse;
4
5/// Represents a chapter from a Bible book.
6///
7/// A chapter contains multiple verses and has a chapter number.
8#[derive(Debug, Clone)]
9pub struct Chapter {
10    verses: Vec<Verse>,
11    chapter_number: usize,
12}
13
14impl Chapter {
15    /// Creates a new chapter with the given verses and chapter number.
16    ///
17    /// # Arguments
18    ///
19    /// * `verses` - A vector of verses in this chapter
20    /// * `chapter_number` - The chapter number within the book
21    pub fn new(verses: Vec<Verse>, chapter_number: usize) -> Self {
22        Chapter {
23            verses,
24            chapter_number,
25        }
26    }
27
28    /// Returns this chapter's number within its book.
29    pub fn number(&self) -> usize {
30        self.chapter_number
31    }
32
33    /// Returns a slice of all verses in this chapter.
34    ///
35    /// # Returns
36    ///
37    /// A slice containing the verses in this chapter.
38    pub fn get_verses(&self) -> &[Verse] {
39        &self.verses
40    }
41
42    /// Returns a specific verse by its verse number.
43    ///
44    /// # Arguments
45    ///
46    /// * `verse_number` - The verse number to retrieve
47    ///
48    /// # Returns
49    ///
50    /// An optional reference to the verse if found, None otherwise.
51    pub fn get_verse(&self, verse_number: usize) -> Option<&Verse> {
52        if verse_number == 0 {
53            return None;
54        }
55        self.verses.get(verse_number - 1)
56    }
57}
58
59impl fmt::Display for Chapter {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        let verses_str = self
62            .verses
63            .iter()
64            .map(|v| format!("{}", v))
65            .collect::<Vec<String>>()
66            .join("\n");
67        write!(f, "Chapter {}:\n{}", self.chapter_number, verses_str)
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74    use crate::bible_books_enum::BibleBook;
75
76    #[test]
77    fn test_new_and_accessors() {
78        let verses = vec![Verse::new(BibleBook::Genesis, 1, 1, "Test".into())];
79        let chapter = Chapter::new(verses, 1);
80        assert_eq!(chapter.number(), 1);
81        assert_eq!(chapter.get_verses().len(), 1);
82        assert_eq!(chapter.get_verse(1).unwrap().number(), 1);
83        assert!(chapter.get_verse(0).is_none());
84    }
85
86    #[test]
87    fn test_clone_independence() {
88        let verses = vec![Verse::new(BibleBook::Genesis, 1, 1, "Clone".into())];
89        let original = Chapter::new(verses, 1);
90        let cloned = original.clone();
91
92        assert_eq!(original.number(), cloned.number());
93        assert_eq!(original.get_verses().len(), cloned.get_verses().len());
94        assert_eq!(
95            original.get_verses()[0].text(),
96            cloned.get_verses()[0].text()
97        );
98
99        // Ensure the cloned chapter owns its data
100        assert_ne!(original.get_verses().as_ptr(), cloned.get_verses().as_ptr());
101        assert_ne!(
102            original.get_verses()[0].text().as_ptr(),
103            cloned.get_verses()[0].text().as_ptr()
104        );
105    }
106}