world: add section iterator

An (empty for now) trait is introduced to abstract over the two section
types.
This commit is contained in:
Matthias Schiffer 2023-02-12 16:19:41 +01:00
parent 2d782f25b1
commit c130f3cdae
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
2 changed files with 124 additions and 2 deletions

View file

@ -1,10 +1,13 @@
use std::collections::BTreeMap;
use std::{
collections::{btree_map, BTreeMap},
iter::{self, FusedIterator},
};
use anyhow::{bail, Context, Result};
use super::{
de,
section::{OldSection, PaletteSection, PaletteSectionBiomes},
section::{OldSection, PaletteSection, PaletteSectionBiomes, Section},
};
use crate::types::*;
@ -23,6 +26,25 @@ pub enum Chunk<'a> {
Empty,
}
#[derive(Debug, Clone)]
enum SectionIterInner<'a> {
V1_18 {
iter: btree_map::Iter<'a, SectionY, (PaletteSection<'a>, PaletteSectionBiomes<'a>)>,
},
V1_13 {
iter: btree_map::Iter<'a, SectionY, PaletteSection<'a>>,
},
Old {
iter: btree_map::Iter<'a, SectionY, OldSection<'a>>,
},
Empty,
}
#[derive(Debug, Clone)]
pub struct SectionIter<'a> {
inner: SectionIterInner<'a>,
}
impl<'a> Chunk<'a> {
pub fn new(data: &'a de::Chunk) -> Result<Self> {
let data_version = data.data_version.unwrap_or_default();
@ -108,4 +130,98 @@ impl<'a> Chunk<'a> {
},
)
}
pub fn sections(&self) -> SectionIter {
use SectionIterInner::*;
SectionIter {
inner: match self {
Chunk::V1_18 { section_map } => V1_18 {
iter: section_map.iter(),
},
Chunk::V1_13 { section_map, .. } => V1_13 {
iter: section_map.iter(),
},
Chunk::Old { section_map, .. } => Old {
iter: section_map.iter(),
},
Chunk::Empty => Empty,
},
}
}
}
trait SectionIterTrait<'a>:
Iterator<Item = (SectionY, &'a dyn Section)>
+ DoubleEndedIterator
+ ExactSizeIterator
+ FusedIterator
{
}
impl<'a, T> SectionIterTrait<'a> for T where
T: Iterator<Item = (SectionY, &'a dyn Section)>
+ DoubleEndedIterator
+ ExactSizeIterator
+ FusedIterator
{
}
impl<'a> SectionIter<'a> {
fn with_iter<F, T>(&mut self, f: F) -> T
where
F: FnOnce(&mut dyn SectionIterTrait<'a>) -> T,
{
match &mut self.inner {
SectionIterInner::V1_18 { iter } => f(
&mut iter.map(|(y, section)| -> (SectionY, &'a dyn Section) { (*y, &section.0) })
),
SectionIterInner::V1_13 { iter } => {
f(&mut iter.map(|(y, section)| -> (SectionY, &'a dyn Section) { (*y, section) }))
}
SectionIterInner::Old { iter } => {
f(&mut iter.map(|(y, section)| -> (SectionY, &'a dyn Section) { (*y, section) }))
}
SectionIterInner::Empty => f(&mut iter::empty()),
}
}
}
impl<'a> Iterator for SectionIter<'a> {
type Item = (SectionY, &'a dyn Section);
fn next(&mut self) -> Option<Self::Item> {
self.with_iter(|iter| iter.next())
}
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.inner {
SectionIterInner::V1_18 { iter } => iter.size_hint(),
SectionIterInner::V1_13 { iter } => iter.size_hint(),
SectionIterInner::Old { iter } => iter.size_hint(),
SectionIterInner::Empty => (0, Some(0)),
}
}
fn last(mut self) -> Option<Self::Item> {
self.with_iter(|iter| iter.last())
}
}
impl<'a> DoubleEndedIterator for SectionIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
self.with_iter(|iter| iter.next_back())
}
}
impl<'a> ExactSizeIterator for SectionIter<'a> {
fn len(&self) -> usize {
match &self.inner {
SectionIterInner::V1_18 { iter } => iter.len(),
SectionIterInner::V1_13 { iter } => iter.len(),
SectionIterInner::Old { iter } => iter.len(),
SectionIterInner::Empty => 0,
}
}
}
impl<'a> FusedIterator for SectionIter<'a> {}

View file

@ -15,6 +15,8 @@ fn palette_bits(len: usize, min: u8, max: u8) -> Option<u8> {
Some(bits)
}
pub trait Section {}
#[derive(Debug)]
pub struct PaletteSectionBiomes<'a> {
biomes: Option<&'a fastnbt::LongArray>,
@ -81,6 +83,8 @@ impl<'a> PaletteSection<'a> {
}
}
impl<'a> Section for PaletteSection<'a> {}
#[derive(Debug)]
pub struct OldSection<'a> {
blocks: &'a fastnbt::ByteArray,
@ -93,3 +97,5 @@ impl<'a> OldSection<'a> {
Ok(Self { blocks, data })
}
}
impl<'a> Section for OldSection<'a> {}