MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / next_section

Method next_section

atomic-core/src/change/format_v3/reader/sections.rs:113–170  ·  view source on GitHub ↗

Read the next section, decompressing its payload. Returns `None` if all sections have been read. The returned [`ReadSection`] contains the decompressed payload and metadata. The compressed bytes of hashed sections are fed through the blake3 hasher for later verification. # Errors - [`FormatError::InvalidSectionType`] if the section type is unknown. - [`FormatError::Decompress`] if zstd decompr

(&mut self)

Source from the content-addressed store, hash-verified

111 /// }
112 /// ```
113 pub fn next_section(&mut self) -> FormatResult<Option<ReadSection>> {
114 // Ensure we have a peeked header (reads from source if needed)
115 if self.peeked.is_none() && self.peek_section_type()?.is_none() {
116 return Ok(None);
117 }
118
119 let peeked = self.peeked.take().unwrap();
120
121 // Read the compressed payload
122 let mut compressed = vec![0u8; peeked.compressed_len as usize];
123 self.reader.read_exact(&mut compressed)?;
124
125 // Feed through hasher if this is a hashed section
126 if peeked.section_type.is_hashed() {
127 self.hasher.update(&peeked.header_bytes);
128 self.hasher.update(&compressed);
129 }
130
131 // Decompress
132 let decompressed = if peeked.compressed_len == 0 {
133 Vec::new()
134 } else {
135 zstd::decode_all(&compressed[..]).map_err(|e| FormatError::Decompress(e.to_string()))?
136 };
137
138 // Build content chunk info if applicable
139 let content_chunk_info = peeked.chunk_header.map(|ch| ContentChunkInfo {
140 chunk_index: ch.chunk_index,
141 chunk_hash: ch.chunk_hash,
142 uncompressed_len: ch.uncompressed_len,
143 });
144
145 // Update stats
146 let header_size = peeked.header_bytes.len() as u64;
147 self.stats.sections_read += 1;
148 self.stats.total_compressed += peeked.compressed_len as u64;
149 self.stats.total_decompressed += decompressed.len() as u64;
150 self.stats.total_bytes_read += header_size + peeked.compressed_len as u64;
151 self.remaining_sections = self.remaining_sections.saturating_sub(1);
152
153 match peeked.section_type {
154 SectionType::Graph => self.stats.graph_sections_read += 1,
155 SectionType::Semantic => self.stats.semantic_sections_read += 1,
156 SectionType::Content => self.stats.content_chunks_read += 1,
157 _ => {}
158 }
159
160 if self.remaining_sections == 0 {
161 self.sections_exhausted = true;
162 }
163
164 Ok(Some(ReadSection {
165 section_type: peeked.section_type,
166 payload: decompressed,
167 compressed_size: peeked.compressed_len,
168 content_chunk_info,
169 }))
170 }

Calls 6

is_noneMethod · 0.80
peek_section_typeMethod · 0.80
updateMethod · 0.80
unwrapMethod · 0.45
is_hashedMethod · 0.45
lenMethod · 0.45