1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
4use core::mem;
5use std::{
6 fmt::Debug,
7 io::{self, Cursor, Read, Seek, SeekFrom, Write},
8 marker::PhantomData,
9 ops::Range,
10};
11
12use super::{block_id::*, block_ref::*, byte_index::*, node_id::*, read_write::*, *};
13use crate::{
14 block_sig::compute_sig, crc::compute_crc, AnsiPstFile, PstFile, PstReader, UnicodePstFile,
15};
16
17#[repr(u8)]
22#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
23pub enum PageType {
24 #[default]
25 None = 0x00,
26 BlockBTree = 0x80,
28 NodeBTree = 0x81,
30 FreeMap = 0x82,
32 AllocationPageMap = 0x83,
34 AllocationMap = 0x84,
36 FreePageMap = 0x85,
38 DensityList = 0x86,
40}
41
42impl TryFrom<u8> for PageType {
43 type Error = NdbError;
44
45 fn try_from(value: u8) -> Result<Self, Self::Error> {
46 match value {
47 0x80 => Ok(PageType::BlockBTree),
48 0x81 => Ok(PageType::NodeBTree),
49 0x82 => Ok(PageType::FreeMap),
50 0x83 => Ok(PageType::AllocationPageMap),
51 0x84 => Ok(PageType::AllocationMap),
52 0x85 => Ok(PageType::FreePageMap),
53 0x86 => Ok(PageType::DensityList),
54 _ => Err(NdbError::InvalidPageType(value)),
55 }
56 }
57}
58
59impl PageType {
60 pub fn signature(&self, index: u64, block_id: u64) -> u16 {
61 match self {
62 PageType::BlockBTree | PageType::NodeBTree | PageType::DensityList => compute_sig(
63 (index & u64::from(u32::MAX)) as u32,
64 (block_id & u64::from(u32::MAX)) as u32,
65 ),
66 _ => 0,
67 }
68 }
69}
70
71pub const PAGE_SIZE: usize = 512;
72
73pub trait PageTrailer {
75 type BlockId: BlockId + Debug;
76
77 fn page_type(&self) -> PageType;
78 fn signature(&self) -> u16;
79 fn crc(&self) -> u32;
80 fn block_id(&self) -> Self::BlockId;
81}
82
83#[derive(Copy, Clone, Default)]
84pub struct UnicodePageTrailer {
85 page_type: PageType,
86 signature: u16,
87 crc: u32,
88 block_id: UnicodePageId,
89}
90
91impl PageTrailer for UnicodePageTrailer {
92 type BlockId = UnicodePageId;
93
94 fn page_type(&self) -> PageType {
95 self.page_type
96 }
97
98 fn signature(&self) -> u16 {
99 self.signature
100 }
101
102 fn crc(&self) -> u32 {
103 self.crc
104 }
105
106 fn block_id(&self) -> UnicodePageId {
107 self.block_id
108 }
109}
110
111impl PageTrailerReadWrite for UnicodePageTrailer {
112 fn new(page_type: PageType, signature: u16, block_id: UnicodePageId, crc: u32) -> Self {
113 Self {
114 page_type,
115 block_id,
116 signature,
117 crc,
118 }
119 }
120
121 fn read(f: &mut dyn Read) -> io::Result<Self> {
122 let mut page_type = [0_u8; 2];
123 f.read_exact(&mut page_type)?;
124 if page_type[0] != page_type[1] {
125 return Err(NdbError::MismatchPageTypeRepeat(page_type[0], page_type[1]).into());
126 }
127 let page_type = PageType::try_from(page_type[0])?;
128 let signature = f.read_u16::<LittleEndian>()?;
129 let crc = f.read_u32::<LittleEndian>()?;
130 let block_id = UnicodePageId::read(f)?;
131
132 Ok(Self {
133 page_type,
134 signature,
135 crc,
136 block_id,
137 })
138 }
139
140 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
141 f.write_all(&[self.page_type as u8; 2])?;
142 f.write_u16::<LittleEndian>(self.signature)?;
143 f.write_u32::<LittleEndian>(self.crc)?;
144 self.block_id.write(f)
145 }
146}
147
148#[derive(Copy, Clone, Default)]
149pub struct AnsiPageTrailer {
150 page_type: PageType,
151 signature: u16,
152 block_id: AnsiPageId,
153 crc: u32,
154}
155
156impl PageTrailer for AnsiPageTrailer {
157 type BlockId = AnsiPageId;
158
159 fn page_type(&self) -> PageType {
160 self.page_type
161 }
162
163 fn signature(&self) -> u16 {
164 self.signature
165 }
166
167 fn crc(&self) -> u32 {
168 self.crc
169 }
170
171 fn block_id(&self) -> AnsiPageId {
172 self.block_id
173 }
174}
175
176impl PageTrailerReadWrite for AnsiPageTrailer {
177 fn new(page_type: PageType, signature: u16, block_id: AnsiPageId, crc: u32) -> Self {
178 Self {
179 page_type,
180 crc,
181 block_id,
182 signature,
183 }
184 }
185
186 fn read(f: &mut dyn Read) -> io::Result<Self> {
187 let mut page_type = [0_u8; 2];
188 f.read_exact(&mut page_type)?;
189 if page_type[0] != page_type[1] {
190 return Err(NdbError::MismatchPageTypeRepeat(page_type[0], page_type[1]).into());
191 }
192 let page_type = PageType::try_from(page_type[0])?;
193 let signature = f.read_u16::<LittleEndian>()?;
194 let block_id = AnsiPageId::read(f)?;
195 let crc = f.read_u32::<LittleEndian>()?;
196
197 Ok(Self {
198 page_type,
199 signature,
200 block_id,
201 crc,
202 })
203 }
204
205 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
206 f.write_all(&[self.page_type as u8; 2])?;
207 f.write_u16::<LittleEndian>(self.signature)?;
208 self.block_id.write(f)?;
209 f.write_u32::<LittleEndian>(self.crc)
210 }
211}
212
213pub type MapBits = [u8; 496];
214
215pub trait MapPage<Pst, const PAGE_TYPE: u8>
216where
217 Pst: PstFile,
218{
219 fn map_bits(&self) -> &MapBits;
220 fn map_bits_mut(&mut self) -> &mut MapBits;
221 fn trailer(&self) -> &Pst::PageTrailer;
222}
223
224const fn leading_zero_count(b: u8) -> u8 {
225 match b {
226 0x00 => 8,
227 b if b < 0x02 => 7,
228 b if b < 0x04 => 6,
229 b if b < 0x08 => 5,
230 b if b < 0x10 => 4,
231 b if b < 0x20 => 3,
232 b if b < 0x40 => 2,
233 b if b < 0x80 => 1,
234 _ => 0,
235 }
236}
237
238const fn trailing_zero_count(b: u8) -> u8 {
239 match b {
240 0x00 => 8,
241 b if b & 0x7F == 0 => 7,
242 b if b & 0x3F == 0 => 6,
243 b if b & 0x1F == 0 => 5,
244 b if b & 0x0F == 0 => 4,
245 b if b & 0x07 == 0 => 3,
246 b if b & 0x03 == 0 => 2,
247 b if b & 0x01 == 0 => 1,
248 _ => 0,
249 }
250}
251
252pub trait AllocationMapPage<Pst>: MapPage<Pst, { PageType::AllocationMap as u8 }>
254where
255 Pst: PstFile,
256{
257 fn find_free_bits(&self, max_size: u16) -> Range<u16> {
259 let mut max_free_slots = 0..0;
260 let mut current = 0..0;
261
262 for &page in self.map_bits() {
263 if page == 0 {
264 current.end += 8;
265 if current.end - current.start > max_free_slots.end - max_free_slots.start {
266 max_free_slots = current.clone();
267 }
268 } else {
269 let leading_zero = u16::from(leading_zero_count(page));
270 let trailing_zero = u16::from(trailing_zero_count(page));
271 assert!(leading_zero + trailing_zero < 8, "leading_zero: {leading_zero}, trailing_zero: {trailing_zero} for page: 0x{page:02X}");
272
273 let page_offset = current.end + 8;
274 current.end += leading_zero;
275
276 if current.end - current.start > max_free_slots.end - max_free_slots.start {
277 max_free_slots = current.clone();
278 }
279
280 if page != 0xFF
281 && (max_free_slots.end - max_free_slots.start + 2)
282 < (8 - trailing_zero - leading_zero)
283 {
284 let mut current = (current.end + 1)..(current.end + 1);
285
286 for i in (leading_zero + 1)..(7 - trailing_zero) {
287 if page & (0x80 >> i) == 0 {
288 current.end += 1;
289 } else {
290 if current.end - current.start
291 > max_free_slots.end - max_free_slots.start
292 {
293 max_free_slots = current.clone();
294 }
295 current = (current.end + 1)..(current.end + 1);
296 }
297 }
298
299 if current.end - current.start > max_free_slots.end - max_free_slots.start {
300 max_free_slots = current;
301 }
302 }
303
304 current = (page_offset - trailing_zero)..page_offset;
305 }
306
307 if max_free_slots.end - max_free_slots.start >= max_size {
308 break;
309 }
310 }
311
312 if current.end - current.start > max_free_slots.end - max_free_slots.start {
313 max_free_slots = current;
314 }
315
316 (max_free_slots.start)..(max_free_slots.end.min(max_free_slots.start + max_size))
317 }
318}
319
320impl<Pst, Page> AllocationMapPage<Pst> for Page
321where
322 Pst: PstFile,
323 Page: MapPage<Pst, { PageType::AllocationMap as u8 }>,
324{
325}
326
327pub trait AllocationPageMapPage<Pst>: MapPage<Pst, { PageType::AllocationPageMap as u8 }>
329where
330 Pst: PstFile,
331{
332}
333
334impl<Pst, Page> AllocationPageMapPage<Pst> for Page
335where
336 Pst: PstFile,
337 Page: MapPage<Pst, { PageType::AllocationPageMap as u8 }>,
338{
339}
340
341pub trait FreeMapPage<Pst>: MapPage<Pst, { PageType::FreeMap as u8 }>
343where
344 Pst: PstFile,
345{
346}
347
348impl<Pst, Page> FreeMapPage<Pst> for Page
349where
350 Pst: PstFile,
351 Page: MapPage<Pst, { PageType::FreeMap as u8 }>,
352{
353}
354
355pub trait FreePageMapPage<Pst>: MapPage<Pst, { PageType::FreePageMap as u8 }>
357where
358 Pst: PstFile,
359{
360}
361
362impl<Pst, Page> FreePageMapPage<Pst> for Page
363where
364 Pst: PstFile,
365 Page: MapPage<Pst, { PageType::FreePageMap as u8 }>,
366{
367}
368
369pub struct UnicodeMapPage<const P: u8> {
370 map_bits: MapBits,
371 trailer: UnicodePageTrailer,
372}
373
374impl<const PAGE_TYPE: u8> MapPage<UnicodePstFile, PAGE_TYPE> for UnicodeMapPage<PAGE_TYPE> {
375 fn map_bits(&self) -> &MapBits {
376 &self.map_bits
377 }
378
379 fn map_bits_mut(&mut self) -> &mut MapBits {
380 &mut self.map_bits
381 }
382
383 fn trailer(&self) -> &UnicodePageTrailer {
384 &self.trailer
385 }
386}
387
388impl<const PAGE_TYPE: u8> MapPageReadWrite<UnicodePstFile, PAGE_TYPE>
389 for UnicodeMapPage<PAGE_TYPE>
390{
391 fn new(map_bits: MapBits, trailer: UnicodePageTrailer) -> NdbResult<Self> {
392 if trailer.page_type() as u8 != PAGE_TYPE {
393 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
394 }
395 Ok(Self { map_bits, trailer })
396 }
397
398 fn read(f: &mut dyn Read) -> io::Result<Self> {
399 let mut map_bits = [0_u8; mem::size_of::<MapBits>()];
400 f.read_exact(&mut map_bits)?;
401
402 let trailer = UnicodePageTrailer::read(f)?;
403 if trailer.page_type() as u8 != PAGE_TYPE {
404 return Err(NdbError::UnexpectedPageType(trailer.page_type()).into());
405 }
406
407 let crc = compute_crc(0, &map_bits);
408 if crc != trailer.crc() {
409 return Err(NdbError::InvalidPageCrc(crc).into());
410 }
411
412 Ok(Self { map_bits, trailer })
413 }
414
415 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
416 f.write_all(&self.map_bits)?;
417
418 let crc = compute_crc(0, &self.map_bits);
419 let trailer = UnicodePageTrailer {
420 crc,
421 ..self.trailer
422 };
423 trailer.write(f)
424 }
425}
426
427pub struct AnsiMapPage<const P: u8> {
428 map_bits: MapBits,
429 trailer: AnsiPageTrailer,
430 padding: u32,
431}
432
433impl<const PAGE_TYPE: u8> MapPage<AnsiPstFile, PAGE_TYPE> for AnsiMapPage<PAGE_TYPE> {
434 fn map_bits(&self) -> &MapBits {
435 &self.map_bits
436 }
437
438 fn map_bits_mut(&mut self) -> &mut MapBits {
439 &mut self.map_bits
440 }
441
442 fn trailer(&self) -> &AnsiPageTrailer {
443 &self.trailer
444 }
445}
446
447impl MapPageReadWrite<AnsiPstFile, { PageType::AllocationMap as u8 }>
448 for AnsiMapPage<{ PageType::AllocationMap as u8 }>
449{
450 fn new(amap_bits: MapBits, trailer: AnsiPageTrailer) -> NdbResult<Self> {
451 if trailer.page_type() != PageType::AllocationMap {
452 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
453 }
454 Ok(Self {
455 map_bits: amap_bits,
456 trailer,
457 padding: 0,
458 })
459 }
460
461 fn read(f: &mut dyn Read) -> io::Result<Self> {
462 let mut buffer = [0_u8; 500];
463 f.read_exact(&mut buffer)?;
464 let mut cursor = Cursor::new(buffer);
465
466 let padding = cursor.read_u32::<LittleEndian>()?;
467
468 let mut map_bits = [0_u8; mem::size_of::<MapBits>()];
469 cursor.read_exact(&mut map_bits)?;
470
471 let buffer = cursor.into_inner();
472
473 let trailer = AnsiPageTrailer::read(f)?;
474 if trailer.page_type() != PageType::AllocationMap {
475 return Err(NdbError::UnexpectedPageType(trailer.page_type()).into());
476 }
477
478 let crc = compute_crc(0, &buffer);
479 if crc != trailer.crc() {
480 return Err(NdbError::InvalidPageCrc(crc).into());
481 }
482
483 Ok(Self {
484 map_bits,
485 trailer,
486 padding,
487 })
488 }
489
490 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
491 let mut cursor = Cursor::new([0_u8; 500]);
492
493 cursor.write_u32::<LittleEndian>(self.padding)?;
494 cursor.write_all(&self.map_bits)?;
495
496 let buffer = cursor.into_inner();
497 let crc = compute_crc(0, &buffer);
498
499 f.write_all(&buffer)?;
500
501 let trailer = AnsiPageTrailer {
502 crc,
503 ..self.trailer
504 };
505 trailer.write(f)
506 }
507}
508
509impl MapPageReadWrite<AnsiPstFile, { PageType::AllocationPageMap as u8 }>
510 for AnsiMapPage<{ PageType::AllocationPageMap as u8 }>
511{
512 fn new(amap_bits: MapBits, trailer: AnsiPageTrailer) -> NdbResult<Self> {
513 if trailer.page_type() != PageType::AllocationPageMap {
514 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
515 }
516 Ok(Self {
517 map_bits: amap_bits,
518 trailer,
519 padding: 0,
520 })
521 }
522
523 fn read(f: &mut dyn Read) -> io::Result<Self> {
524 let mut buffer = [0_u8; 500];
525 f.read_exact(&mut buffer)?;
526 let mut cursor = Cursor::new(buffer);
527
528 let padding = cursor.read_u32::<LittleEndian>()?;
529
530 let mut map_bits = [0_u8; mem::size_of::<MapBits>()];
531 cursor.read_exact(&mut map_bits)?;
532
533 let buffer = cursor.into_inner();
534
535 let trailer = AnsiPageTrailer::read(f)?;
536 if trailer.page_type() != PageType::AllocationPageMap {
537 return Err(NdbError::UnexpectedPageType(trailer.page_type()).into());
538 }
539
540 let crc = compute_crc(0, &buffer);
541 if crc != trailer.crc() {
542 return Err(NdbError::InvalidPageCrc(crc).into());
543 }
544
545 Ok(Self {
546 map_bits,
547 trailer,
548 padding,
549 })
550 }
551
552 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
553 let mut cursor = Cursor::new([0_u8; 500]);
554
555 cursor.write_u32::<LittleEndian>(self.padding)?;
556 cursor.write_all(&self.map_bits)?;
557
558 let buffer = cursor.into_inner();
559 let crc = compute_crc(0, &buffer);
560
561 f.write_all(&buffer)?;
562
563 let trailer = AnsiPageTrailer {
564 crc,
565 ..self.trailer
566 };
567 trailer.write(f)
568 }
569}
570
571impl MapPageReadWrite<AnsiPstFile, { PageType::FreeMap as u8 }>
572 for AnsiMapPage<{ PageType::FreeMap as u8 }>
573{
574 fn new(amap_bits: MapBits, trailer: AnsiPageTrailer) -> NdbResult<Self> {
575 if trailer.page_type() != PageType::FreeMap {
576 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
577 }
578 Ok(Self {
579 map_bits: amap_bits,
580 trailer,
581 padding: 0,
582 })
583 }
584
585 fn read(f: &mut dyn Read) -> io::Result<Self> {
586 let mut buffer = [0_u8; 500];
587 f.read_exact(&mut buffer)?;
588 let mut cursor = Cursor::new(buffer);
589
590 let mut map_bits = [0_u8; mem::size_of::<MapBits>()];
591 cursor.read_exact(&mut map_bits)?;
592
593 let padding = cursor.read_u32::<LittleEndian>()?;
594
595 let buffer = cursor.into_inner();
596
597 let trailer = AnsiPageTrailer::read(f)?;
598 if trailer.page_type() != PageType::FreeMap {
599 return Err(NdbError::UnexpectedPageType(trailer.page_type()).into());
600 }
601
602 let crc = compute_crc(0, &buffer);
603 if crc != trailer.crc() {
604 return Err(NdbError::InvalidPageCrc(crc).into());
605 }
606
607 Ok(Self {
608 map_bits,
609 trailer,
610 padding,
611 })
612 }
613
614 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
615 let mut cursor = Cursor::new([0_u8; 500]);
616
617 cursor.write_all(&self.map_bits)?;
618 cursor.write_u32::<LittleEndian>(self.padding)?;
619
620 let buffer = cursor.into_inner();
621 let crc = compute_crc(0, &buffer);
622
623 f.write_all(&buffer)?;
624
625 let trailer = AnsiPageTrailer {
626 crc,
627 ..self.trailer
628 };
629 trailer.write(f)
630 }
631}
632
633impl MapPageReadWrite<AnsiPstFile, { PageType::FreePageMap as u8 }>
634 for AnsiMapPage<{ PageType::FreePageMap as u8 }>
635{
636 fn new(amap_bits: MapBits, trailer: AnsiPageTrailer) -> NdbResult<Self> {
637 if trailer.page_type() != PageType::FreePageMap {
638 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
639 }
640 Ok(Self {
641 map_bits: amap_bits,
642 trailer,
643 padding: 0,
644 })
645 }
646
647 fn read(f: &mut dyn Read) -> io::Result<Self> {
648 let mut buffer = [0_u8; 500];
649 f.read_exact(&mut buffer)?;
650 let mut cursor = Cursor::new(buffer);
651
652 let mut map_bits = [0_u8; mem::size_of::<MapBits>()];
653 cursor.read_exact(&mut map_bits)?;
654
655 let padding = cursor.read_u32::<LittleEndian>()?;
656
657 let buffer = cursor.into_inner();
658
659 let trailer = AnsiPageTrailer::read(f)?;
660 if trailer.page_type() != PageType::FreePageMap {
661 return Err(NdbError::UnexpectedPageType(trailer.page_type()).into());
662 }
663
664 let crc = compute_crc(0, &buffer);
665 if crc != trailer.crc() {
666 return Err(NdbError::InvalidPageCrc(crc).into());
667 }
668
669 Ok(Self {
670 map_bits,
671 trailer,
672 padding,
673 })
674 }
675
676 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
677 let mut cursor = Cursor::new([0_u8; 500]);
678
679 cursor.write_all(&self.map_bits)?;
680 cursor.write_u32::<LittleEndian>(self.padding)?;
681
682 let buffer = cursor.into_inner();
683 let crc = compute_crc(0, &buffer);
684
685 f.write_all(&buffer)?;
686
687 let trailer = AnsiPageTrailer {
688 crc,
689 ..self.trailer
690 };
691 trailer.write(f)
692 }
693}
694
695const DENSITY_LIST_ENTRY_PAGE_NUMBER_MASK: u32 = 0x000F_FFFF;
696
697#[derive(Copy, Clone, Debug)]
699pub struct DensityListPageEntry(u32);
700
701impl DensityListPageEntry {
702 pub fn new(page: u32, free_slots: u16) -> NdbResult<Self> {
703 if page & !0x000F_FFFF != 0 {
704 return Err(NdbError::InvalidDensityListEntryPageNumber(page));
705 };
706 if free_slots & !0x0FFF != 0 {
707 return Err(NdbError::InvalidDensityListEntryFreeSlots(free_slots));
708 };
709
710 Ok(Self(page | ((free_slots as u32) << 20)))
711 }
712
713 pub fn read(f: &mut dyn Read) -> io::Result<Self> {
714 Ok(Self(f.read_u32::<LittleEndian>()?))
715 }
716
717 pub fn write(&self, f: &mut dyn Write) -> io::Result<()> {
718 f.write_u32::<LittleEndian>(self.0)
719 }
720
721 pub fn page(&self) -> u32 {
722 self.0 & DENSITY_LIST_ENTRY_PAGE_NUMBER_MASK
723 }
724
725 pub fn free_slots(&self) -> u16 {
726 (self.0 >> 20) as u16
727 }
728}
729
730pub const DENSITY_LIST_FILE_OFFSET: u64 = 0x4200;
731
732pub trait DensityListPage<Pst>
734where
735 Pst: PstFile,
736{
737 fn backfill_complete(&self) -> bool;
738 fn current_page(&self) -> u32;
739 fn entries(&self) -> &[DensityListPageEntry];
740 fn trailer(&self) -> &<Pst as PstFile>::PageTrailer;
741}
742
743pub struct UnicodeDensityListPage {
744 backfill_complete: bool,
745 current_page: u32,
746 entry_count: u8,
747 entries:
748 [DensityListPageEntry; <Self as DensityListPageReadWrite<UnicodePstFile>>::MAX_ENTRIES],
749 trailer: UnicodePageTrailer,
750}
751
752impl DensityListPage<UnicodePstFile> for UnicodeDensityListPage {
753 fn backfill_complete(&self) -> bool {
754 self.backfill_complete
755 }
756
757 fn current_page(&self) -> u32 {
758 self.current_page
759 }
760
761 fn entries(&self) -> &[DensityListPageEntry] {
762 &self.entries[..self.entry_count as usize]
763 }
764
765 fn trailer(&self) -> &UnicodePageTrailer {
766 &self.trailer
767 }
768}
769
770impl DensityListPageReadWrite<UnicodePstFile> for UnicodeDensityListPage {
771 const MAX_ENTRIES: usize = 476 / mem::size_of::<DensityListPageEntry>();
772
773 fn new(
774 backfill_complete: bool,
775 current_page: u32,
776 entries: &[DensityListPageEntry],
777 trailer: UnicodePageTrailer,
778 ) -> NdbResult<Self> {
779 if entries.len() > Self::MAX_ENTRIES {
780 return Err(NdbError::InvalidDensityListEntryCount(entries.len()));
781 }
782
783 if trailer.page_type() != PageType::DensityList {
784 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
785 }
786
787 let entry_count = entries.len() as u8;
788
789 let mut buffer = [DensityListPageEntry(0); Self::MAX_ENTRIES];
790 buffer[..entries.len()].copy_from_slice(entries);
791 let entries = buffer;
792
793 Ok(Self {
794 backfill_complete,
795 current_page,
796 entry_count,
797 entries,
798 trailer,
799 })
800 }
801
802 fn read<R: PstReader>(f: &mut R) -> io::Result<Self> {
803 f.seek(SeekFrom::Start(DENSITY_LIST_FILE_OFFSET))?;
804
805 let mut buffer = [0_u8; 496];
806 f.read_exact(&mut buffer)?;
807 let mut cursor = Cursor::new(buffer);
808
809 let backfill_complete = cursor.read_u8()? & 0x01 != 0;
811
812 let entry_count = cursor.read_u8()?;
814 if entry_count > Self::MAX_ENTRIES as u8 {
815 return Err(NdbError::InvalidDensityListEntryCount(entry_count as usize).into());
816 }
817
818 if cursor.read_u16::<LittleEndian>()? != 0 {
820 return Err(NdbError::InvalidDensityListPadding.into());
821 }
822
823 let current_page = cursor.read_u32::<LittleEndian>()?;
825
826 let mut entries = [DensityListPageEntry(0); Self::MAX_ENTRIES];
828 for entry in entries.iter_mut().take(entry_count as usize) {
829 *entry = DensityListPageEntry::read(&mut cursor)?;
830 }
831 cursor.seek(SeekFrom::Current(
832 ((Self::MAX_ENTRIES - entry_count as usize) * mem::size_of::<DensityListPageEntry>())
833 as i64,
834 ))?;
835
836 let mut padding = [0_u8; 12];
838 cursor.read_exact(&mut padding)?;
839 if padding != [0; 12] {
840 return Err(NdbError::InvalidDensityListPadding.into());
841 }
842
843 let buffer = cursor.into_inner();
844
845 let trailer = UnicodePageTrailer::read(f)?;
847 if trailer.page_type() != PageType::DensityList {
848 return Err(NdbError::UnexpectedPageType(trailer.page_type()).into());
849 }
850
851 let crc = compute_crc(0, &buffer);
852 if crc != trailer.crc() {
853 return Err(NdbError::InvalidPageCrc(crc).into());
854 }
855
856 Ok(Self {
857 backfill_complete,
858 current_page,
859 entry_count,
860 entries,
861 trailer,
862 })
863 }
864
865 fn write<W: Write + Seek>(&self, f: &mut W) -> io::Result<()> {
866 let mut cursor = Cursor::new([0_u8; 496]);
867
868 cursor.write_u8(if self.backfill_complete { 0x01 } else { 0 })?;
870
871 cursor.write_u8(self.entry_count)?;
873
874 cursor.write_u16::<LittleEndian>(0)?;
876
877 cursor.write_u32::<LittleEndian>(self.current_page)?;
879
880 for entry in self.entries.iter() {
882 entry.write(&mut cursor)?;
883 }
884
885 cursor.write_all(&[0; 12])?;
887
888 let buffer = cursor.into_inner();
889 let crc = compute_crc(0, &buffer);
890
891 f.seek(SeekFrom::Start(DENSITY_LIST_FILE_OFFSET))?;
892 f.write_all(&buffer)?;
893
894 let trailer = UnicodePageTrailer {
896 crc,
897 ..self.trailer
898 };
899 trailer.write(f)
900 }
901}
902
903pub struct AnsiDensityListPage {
904 backfill_complete: bool,
905 current_page: u32,
906 entry_count: u8,
907 entries: [DensityListPageEntry; <Self as DensityListPageReadWrite<AnsiPstFile>>::MAX_ENTRIES],
908 trailer: AnsiPageTrailer,
909}
910
911impl DensityListPage<AnsiPstFile> for AnsiDensityListPage {
912 fn backfill_complete(&self) -> bool {
913 self.backfill_complete
914 }
915
916 fn current_page(&self) -> u32 {
917 self.current_page
918 }
919
920 fn entries(&self) -> &[DensityListPageEntry] {
921 &self.entries[..self.entry_count as usize]
922 }
923
924 fn trailer(&self) -> &AnsiPageTrailer {
925 &self.trailer
926 }
927}
928
929impl DensityListPageReadWrite<AnsiPstFile> for AnsiDensityListPage {
930 const MAX_ENTRIES: usize = 480 / mem::size_of::<DensityListPageEntry>();
931
932 fn new(
933 backfill_complete: bool,
934 current_page: u32,
935 entries: &[DensityListPageEntry],
936 trailer: AnsiPageTrailer,
937 ) -> NdbResult<Self> {
938 if entries.len() > Self::MAX_ENTRIES {
939 return Err(NdbError::InvalidDensityListEntryCount(entries.len()));
940 }
941
942 if trailer.page_type() != PageType::DensityList {
943 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
944 }
945
946 let entry_count = entries.len() as u8;
947
948 let mut buffer = [DensityListPageEntry(0); Self::MAX_ENTRIES];
949 buffer[..entries.len()].copy_from_slice(entries);
950 let entries = buffer;
951
952 Ok(Self {
953 backfill_complete,
954 current_page,
955 entry_count,
956 entries,
957 trailer,
958 })
959 }
960
961 fn read<R: PstReader>(f: &mut R) -> io::Result<Self> {
962 f.seek(SeekFrom::Start(DENSITY_LIST_FILE_OFFSET))?;
963
964 let mut buffer = [0_u8; 500];
965 f.read_exact(&mut buffer)?;
966 let mut cursor = Cursor::new(buffer);
967
968 let backfill_complete = cursor.read_u8()? & 0x01 != 0;
970
971 let entry_count = cursor.read_u8()?;
973 if entry_count > Self::MAX_ENTRIES as u8 {
974 return Err(NdbError::InvalidDensityListEntryCount(entry_count as usize).into());
975 }
976
977 if cursor.read_u16::<LittleEndian>()? != 0 {
979 return Err(NdbError::InvalidDensityListPadding.into());
980 }
981
982 let current_page = cursor.read_u32::<LittleEndian>()?;
984
985 let mut entries = [DensityListPageEntry(0); Self::MAX_ENTRIES];
987 for entry in entries.iter_mut().take(entry_count as usize) {
988 *entry = DensityListPageEntry::read(&mut cursor)?;
989 }
990 cursor.seek(SeekFrom::Current(
991 ((Self::MAX_ENTRIES - entry_count as usize) * mem::size_of::<DensityListPageEntry>())
992 as i64,
993 ))?;
994
995 let mut padding = [0_u8; 12];
997 cursor.read_exact(&mut padding)?;
998 if padding != [0; 12] {
999 return Err(NdbError::InvalidDensityListPadding.into());
1000 }
1001
1002 let buffer = cursor.into_inner();
1003
1004 let trailer = AnsiPageTrailer::read(f)?;
1006 if trailer.page_type() != PageType::DensityList {
1007 return Err(NdbError::UnexpectedPageType(trailer.page_type()).into());
1008 }
1009
1010 let crc = compute_crc(0, &buffer);
1011 if crc != trailer.crc() {
1012 return Err(NdbError::InvalidPageCrc(crc).into());
1013 }
1014
1015 Ok(Self {
1016 backfill_complete,
1017 current_page,
1018 entry_count,
1019 entries,
1020 trailer,
1021 })
1022 }
1023
1024 fn write<W: Write + Seek>(&self, f: &mut W) -> io::Result<()> {
1025 let mut cursor = Cursor::new([0_u8; 500]);
1026
1027 cursor.write_u8(if self.backfill_complete { 0x01 } else { 0 })?;
1029
1030 cursor.write_u8(self.entry_count)?;
1032
1033 cursor.write_u16::<LittleEndian>(0)?;
1035
1036 cursor.write_u32::<LittleEndian>(self.current_page)?;
1038
1039 for entry in self.entries.iter() {
1041 entry.write(&mut cursor)?;
1042 }
1043
1044 cursor.write_all(&[0; 12])?;
1046
1047 let buffer = cursor.into_inner();
1048 let crc = compute_crc(0, &buffer);
1049
1050 f.seek(SeekFrom::Start(DENSITY_LIST_FILE_OFFSET))?;
1051 f.write_all(&buffer)?;
1052
1053 let trailer = AnsiPageTrailer {
1055 crc,
1056 ..self.trailer
1057 };
1058 trailer.write(f)
1059 }
1060}
1061
1062pub trait BTreeEntryKey: Copy + Sized + Into<u64> + From<u32> {}
1063
1064impl BTreeEntryKey for u32 {}
1065impl BTreeEntryKey for u64 {}
1066
1067pub trait BTreeEntry: Copy + Sized {
1068 type Key: BTreeEntryKey;
1069
1070 fn key(&self) -> Self::Key;
1071}
1072
1073pub trait BTreePage {
1075 type Entry: BTreeEntry;
1076 type Trailer: PageTrailer;
1077
1078 fn level(&self) -> u8;
1079 fn entries(&self) -> &[Self::Entry];
1080 fn trailer(&self) -> &Self::Trailer;
1081}
1082
1083pub struct UnicodeBTreeEntryPage {
1084 level: u8,
1085 max_entries: u8,
1086 entry_size: u8,
1087 entries: Vec<UnicodeBTreePageEntry>,
1088 trailer: UnicodePageTrailer,
1089}
1090
1091impl UnicodeBTreeEntryPage {
1092 pub fn new(
1093 level: u8,
1094 max_entries: u8,
1095 entry_size: u8,
1096 entries: &[UnicodeBTreePageEntry],
1097 trailer: UnicodePageTrailer,
1098 ) -> NdbResult<Self> {
1099 if !(1..=8).contains(&level) {
1100 return Err(NdbError::InvalidBTreePageLevel(level));
1101 }
1102
1103 if entries.len() > usize::from(max_entries) {
1104 return Err(NdbError::InvalidBTreeEntryCount(entries.len()));
1105 }
1106
1107 if trailer.page_type() != PageType::BlockBTree && trailer.page_type() != PageType::NodeBTree
1108 {
1109 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
1110 }
1111
1112 let entries = entries.to_vec();
1113
1114 Ok(Self {
1115 level,
1116 max_entries,
1117 entry_size,
1118 entries,
1119 trailer,
1120 })
1121 }
1122}
1123
1124impl BTreePage for UnicodeBTreeEntryPage {
1125 type Entry = UnicodeBTreePageEntry;
1126 type Trailer = UnicodePageTrailer;
1127
1128 fn level(&self) -> u8 {
1129 self.level
1130 }
1131
1132 fn entries(&self) -> &[UnicodeBTreePageEntry] {
1133 &self.entries
1134 }
1135
1136 fn trailer(&self) -> &UnicodePageTrailer {
1137 &self.trailer
1138 }
1139}
1140
1141impl BTreePageReadWrite for UnicodeBTreeEntryPage {
1142 fn new(
1143 level: u8,
1144 max_entries: u8,
1145 entry_size: u8,
1146 entries: &[UnicodeBTreePageEntry],
1147 trailer: UnicodePageTrailer,
1148 ) -> NdbResult<Self> {
1149 Self::new(level, max_entries, entry_size, entries, trailer)
1150 }
1151
1152 fn max_entries(&self) -> u8 {
1153 self.max_entries
1154 }
1155
1156 fn entry_size(&self) -> u8 {
1157 self.entry_size
1158 }
1159}
1160
1161impl UnicodeBTreePageReadWrite<UnicodeBTreePageEntry> for UnicodeBTreeEntryPage {}
1162
1163pub struct AnsiBTreeEntryPage {
1164 level: u8,
1165 max_entries: u8,
1166 entry_size: u8,
1167 entries: Vec<AnsiBTreePageEntry>,
1168 trailer: AnsiPageTrailer,
1169}
1170
1171impl BTreePage for AnsiBTreeEntryPage {
1172 type Entry = AnsiBTreePageEntry;
1173 type Trailer = AnsiPageTrailer;
1174
1175 fn level(&self) -> u8 {
1176 self.level
1177 }
1178
1179 fn entries(&self) -> &[AnsiBTreePageEntry] {
1180 &self.entries
1181 }
1182
1183 fn trailer(&self) -> &AnsiPageTrailer {
1184 &self.trailer
1185 }
1186}
1187
1188impl BTreePageReadWrite for AnsiBTreeEntryPage {
1189 fn new(
1190 level: u8,
1191 max_entries: u8,
1192 entry_size: u8,
1193 entries: &[AnsiBTreePageEntry],
1194 trailer: AnsiPageTrailer,
1195 ) -> NdbResult<Self> {
1196 if !(1..=8).contains(&level) {
1197 return Err(NdbError::InvalidBTreePageLevel(level));
1198 }
1199
1200 if entries.len() > usize::from(max_entries) {
1201 return Err(NdbError::InvalidBTreeEntryCount(entries.len()));
1202 }
1203
1204 if trailer.page_type() != PageType::BlockBTree && trailer.page_type() != PageType::NodeBTree
1205 {
1206 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
1207 }
1208
1209 let entries = entries.to_vec();
1210
1211 Ok(Self {
1212 level,
1213 max_entries,
1214 entry_size,
1215 entries,
1216 trailer,
1217 })
1218 }
1219
1220 fn max_entries(&self) -> u8 {
1221 self.max_entries
1222 }
1223
1224 fn entry_size(&self) -> u8 {
1225 self.entry_size
1226 }
1227}
1228
1229impl AnsiBTreePageReadWrite<AnsiBTreePageEntry> for AnsiBTreeEntryPage {}
1230
1231pub trait BTreePageEntry: BTreeEntry {
1233 type Block: BlockRef;
1234
1235 fn block(&self) -> Self::Block;
1236}
1237
1238impl<Entry> BTreeEntryReadWrite for Entry
1239where
1240 Entry: BTreeEntry<Key: BTreePageKeyReadWrite>
1241 + BTreePageEntry<Block: BlockRefReadWrite<Block: BlockIdReadWrite, Index: ByteIndexReadWrite>>
1242 + BTreePageEntryReadWrite,
1243{
1244 const ENTRY_SIZE: usize = <Entry as BTreePageEntryReadWrite>::ENTRY_SIZE;
1245
1246 fn read(f: &mut dyn Read) -> io::Result<Self> {
1247 Ok(Self::new(
1248 <Self as BTreeEntry>::Key::read(f)?,
1249 <Self as BTreePageEntry>::Block::read(f)?,
1250 ))
1251 }
1252
1253 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
1254 self.key().write(f)?;
1255 self.block().write(f)
1256 }
1257}
1258
1259impl BTreePageKeyReadWrite for u64 {
1260 fn read(f: &mut dyn Read) -> io::Result<Self> {
1261 f.read_u64::<LittleEndian>()
1262 }
1263
1264 fn write(self, f: &mut dyn Write) -> io::Result<()> {
1265 f.write_u64::<LittleEndian>(self)
1266 }
1267}
1268
1269#[derive(Copy, Clone, Default, Debug)]
1270pub struct UnicodeBTreePageEntry {
1271 key: u64,
1272 block: UnicodePageRef,
1273}
1274
1275impl BTreeEntry for UnicodeBTreePageEntry {
1276 type Key = u64;
1277
1278 fn key(&self) -> u64 {
1279 self.key
1280 }
1281}
1282
1283impl BTreePageEntry for UnicodeBTreePageEntry {
1284 type Block = UnicodePageRef;
1285
1286 fn block(&self) -> UnicodePageRef {
1287 self.block
1288 }
1289}
1290
1291impl BTreePageEntryReadWrite for UnicodeBTreePageEntry {
1292 const ENTRY_SIZE: usize = 24;
1293
1294 fn new(key: u64, block: UnicodePageRef) -> Self {
1295 Self { key, block }
1296 }
1297}
1298
1299impl BTreePageKeyReadWrite for u32 {
1300 fn read(f: &mut dyn Read) -> io::Result<Self> {
1301 f.read_u32::<LittleEndian>()
1302 }
1303
1304 fn write(self, f: &mut dyn Write) -> io::Result<()> {
1305 f.write_u32::<LittleEndian>(self)
1306 }
1307}
1308
1309#[derive(Copy, Clone, Default, Debug)]
1310pub struct AnsiBTreePageEntry {
1311 key: u32,
1312 block: AnsiPageRef,
1313}
1314
1315impl BTreeEntry for AnsiBTreePageEntry {
1316 type Key = u32;
1317
1318 fn key(&self) -> u32 {
1319 self.key
1320 }
1321}
1322
1323impl BTreePageEntry for AnsiBTreePageEntry {
1324 type Block = AnsiPageRef;
1325
1326 fn block(&self) -> AnsiPageRef {
1327 self.block
1328 }
1329}
1330
1331impl BTreePageEntryReadWrite for AnsiBTreePageEntry {
1332 const ENTRY_SIZE: usize = 12;
1333
1334 fn new(key: u32, block: AnsiPageRef) -> Self {
1335 Self { key, block }
1336 }
1337}
1338
1339pub trait BlockBTreeEntry: BTreeEntry {
1341 type Block: BlockRef;
1342
1343 fn block(&self) -> Self::Block;
1344 fn size(&self) -> u16;
1345 fn ref_count(&self) -> u16;
1346}
1347
1348#[derive(Copy, Clone, Default, Debug)]
1349pub struct UnicodeBlockBTreeEntry {
1350 block: UnicodeBlockRef,
1351 size: u16,
1352 ref_count: u16,
1353 padding: u32,
1354}
1355
1356impl UnicodeBlockBTreeEntry {
1357 pub fn new(block: UnicodeBlockRef, size: u16) -> Self {
1358 Self {
1359 block,
1360 size,
1361 ref_count: 1,
1362 ..Default::default()
1363 }
1364 }
1365}
1366
1367impl BTreeEntry for UnicodeBlockBTreeEntry {
1368 type Key = u64;
1369
1370 fn key(&self) -> u64 {
1371 self.block.block().search_key()
1372 }
1373}
1374
1375impl BTreeEntryReadWrite for UnicodeBlockBTreeEntry {
1376 const ENTRY_SIZE: usize = 24;
1377
1378 fn read(f: &mut dyn Read) -> io::Result<Self> {
1379 let block = UnicodeBlockRef::read(f)?;
1380 let size = f.read_u16::<LittleEndian>()?;
1381 let ref_count = f.read_u16::<LittleEndian>()?;
1382 let padding = f.read_u32::<LittleEndian>()?;
1383
1384 Ok(Self {
1385 block,
1386 size,
1387 ref_count,
1388 padding,
1389 })
1390 }
1391
1392 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
1393 self.block.write(f)?;
1394 f.write_u16::<LittleEndian>(self.size)?;
1395 f.write_u16::<LittleEndian>(self.ref_count)?;
1396 f.write_u32::<LittleEndian>(self.padding)
1397 }
1398}
1399
1400impl BlockBTreeEntry for UnicodeBlockBTreeEntry {
1401 type Block = UnicodeBlockRef;
1402
1403 fn block(&self) -> UnicodeBlockRef {
1404 self.block
1405 }
1406
1407 fn size(&self) -> u16 {
1408 self.size
1409 }
1410
1411 fn ref_count(&self) -> u16 {
1412 self.ref_count
1413 }
1414}
1415
1416impl BlockBTreeEntryReadWrite for UnicodeBlockBTreeEntry {
1417 fn new(block: UnicodeBlockRef, size: u16) -> Self {
1418 Self::new(block, size)
1419 }
1420}
1421
1422pub struct UnicodeBlockBTreePage {
1423 max_entries: u8,
1424 entry_size: u8,
1425 entries: Vec<UnicodeBlockBTreeEntry>,
1426 trailer: UnicodePageTrailer,
1427}
1428
1429impl UnicodeBlockBTreePage {
1430 pub fn new(
1431 level: u8,
1432 max_entries: u8,
1433 entry_size: u8,
1434 entries: &[UnicodeBlockBTreeEntry],
1435 trailer: UnicodePageTrailer,
1436 ) -> NdbResult<Self> {
1437 if level != 0 {
1438 return Err(NdbError::InvalidBTreePageLevel(level));
1439 }
1440
1441 if entries.len() > usize::from(max_entries) {
1442 return Err(NdbError::InvalidBTreeEntryCount(entries.len()));
1443 }
1444
1445 if trailer.page_type() != PageType::BlockBTree {
1446 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
1447 }
1448
1449 let entries = entries.to_vec();
1450
1451 Ok(Self {
1452 max_entries,
1453 entry_size,
1454 entries,
1455 trailer,
1456 })
1457 }
1458}
1459
1460impl BTreePage for UnicodeBlockBTreePage {
1461 type Entry = UnicodeBlockBTreeEntry;
1462 type Trailer = UnicodePageTrailer;
1463
1464 fn level(&self) -> u8 {
1465 0
1466 }
1467
1468 fn entries(&self) -> &[UnicodeBlockBTreeEntry] {
1469 &self.entries
1470 }
1471
1472 fn trailer(&self) -> &UnicodePageTrailer {
1473 &self.trailer
1474 }
1475}
1476
1477impl BTreePageReadWrite for UnicodeBlockBTreePage {
1478 fn new(
1479 level: u8,
1480 max_entries: u8,
1481 entry_size: u8,
1482 entries: &[UnicodeBlockBTreeEntry],
1483 trailer: UnicodePageTrailer,
1484 ) -> NdbResult<Self> {
1485 Self::new(level, max_entries, entry_size, entries, trailer)
1486 }
1487
1488 fn max_entries(&self) -> u8 {
1489 self.max_entries
1490 }
1491
1492 fn entry_size(&self) -> u8 {
1493 self.entry_size
1494 }
1495}
1496
1497impl UnicodeBTreePageReadWrite<UnicodeBlockBTreeEntry> for UnicodeBlockBTreePage {}
1498
1499#[derive(Copy, Clone, Default, Debug)]
1500pub struct AnsiBlockBTreeEntry {
1501 block: AnsiBlockRef,
1502 size: u16,
1503 ref_count: u16,
1504}
1505
1506impl AnsiBlockBTreeEntry {
1507 pub fn new(block: AnsiBlockRef, size: u16) -> Self {
1508 Self {
1509 block,
1510 size,
1511 ref_count: 1,
1512 }
1513 }
1514}
1515
1516impl BTreeEntry for AnsiBlockBTreeEntry {
1517 type Key = u32;
1518
1519 fn key(&self) -> u32 {
1520 self.block.block().search_key()
1521 }
1522}
1523
1524impl BTreeEntryReadWrite for AnsiBlockBTreeEntry {
1525 const ENTRY_SIZE: usize = 12;
1526
1527 fn read(f: &mut dyn Read) -> io::Result<Self> {
1528 Ok(Self {
1529 block: AnsiBlockRef::read(f)?,
1530 size: f.read_u16::<LittleEndian>()?,
1531 ref_count: f.read_u16::<LittleEndian>()?,
1532 })
1533 }
1534
1535 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
1536 self.block.write(f)?;
1537 f.write_u16::<LittleEndian>(self.size)?;
1538 f.write_u16::<LittleEndian>(self.ref_count)
1539 }
1540}
1541
1542impl BlockBTreeEntry for AnsiBlockBTreeEntry {
1543 type Block = AnsiBlockRef;
1544
1545 fn block(&self) -> AnsiBlockRef {
1546 self.block
1547 }
1548
1549 fn size(&self) -> u16 {
1550 self.size
1551 }
1552
1553 fn ref_count(&self) -> u16 {
1554 self.ref_count
1555 }
1556}
1557
1558impl BlockBTreeEntryReadWrite for AnsiBlockBTreeEntry {
1559 fn new(block: AnsiBlockRef, size: u16) -> Self {
1560 Self::new(block, size)
1561 }
1562}
1563
1564pub struct AnsiBlockBTreePage {
1565 max_entries: u8,
1566 entry_size: u8,
1567 entries: Vec<AnsiBlockBTreeEntry>,
1568 trailer: AnsiPageTrailer,
1569}
1570
1571impl AnsiBlockBTreePage {
1572 pub fn new(
1573 level: u8,
1574 max_entries: u8,
1575 entry_size: u8,
1576 entries: &[AnsiBlockBTreeEntry],
1577 trailer: AnsiPageTrailer,
1578 ) -> NdbResult<Self> {
1579 if level != 0 {
1580 return Err(NdbError::InvalidBTreePageLevel(level));
1581 }
1582
1583 if entries.len() > usize::from(max_entries) {
1584 return Err(NdbError::InvalidBTreeEntryCount(entries.len()));
1585 }
1586
1587 if trailer.page_type() != PageType::BlockBTree {
1588 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
1589 }
1590
1591 let entries = entries.to_vec();
1592
1593 Ok(Self {
1594 max_entries,
1595 entry_size,
1596 entries,
1597 trailer,
1598 })
1599 }
1600}
1601
1602impl BTreePage for AnsiBlockBTreePage {
1603 type Entry = AnsiBlockBTreeEntry;
1604 type Trailer = AnsiPageTrailer;
1605
1606 fn level(&self) -> u8 {
1607 0
1608 }
1609
1610 fn entries(&self) -> &[AnsiBlockBTreeEntry] {
1611 &self.entries
1612 }
1613
1614 fn trailer(&self) -> &AnsiPageTrailer {
1615 &self.trailer
1616 }
1617}
1618
1619impl BTreePageReadWrite for AnsiBlockBTreePage {
1620 fn new(
1621 level: u8,
1622 max_entries: u8,
1623 entry_size: u8,
1624 entries: &[AnsiBlockBTreeEntry],
1625 trailer: AnsiPageTrailer,
1626 ) -> NdbResult<Self> {
1627 Self::new(level, max_entries, entry_size, entries, trailer)
1628 }
1629
1630 fn max_entries(&self) -> u8 {
1631 self.max_entries
1632 }
1633
1634 fn entry_size(&self) -> u8 {
1635 self.entry_size
1636 }
1637}
1638
1639impl AnsiBTreePageReadWrite<AnsiBlockBTreeEntry> for AnsiBlockBTreePage {}
1640
1641pub trait NodeBTreeEntry: BTreeEntry {
1643 type Block: BlockId;
1644
1645 fn node(&self) -> NodeId;
1646 fn data(&self) -> Self::Block;
1647 fn sub_node(&self) -> Option<Self::Block>;
1648 fn parent(&self) -> Option<NodeId>;
1649}
1650
1651#[derive(Copy, Clone, Default, Debug)]
1652pub struct UnicodeNodeBTreeEntry {
1653 node: NodeId,
1654 data: UnicodeBlockId,
1655 sub_node: Option<UnicodeBlockId>,
1656 parent: Option<NodeId>,
1657 padding: u32,
1658}
1659
1660impl UnicodeNodeBTreeEntry {
1661 pub fn new(
1662 node: NodeId,
1663 data: UnicodeBlockId,
1664 sub_node: Option<UnicodeBlockId>,
1665 parent: Option<NodeId>,
1666 ) -> Self {
1667 Self {
1668 node,
1669 data,
1670 sub_node,
1671 parent,
1672 ..Default::default()
1673 }
1674 }
1675}
1676
1677impl BTreeEntry for UnicodeNodeBTreeEntry {
1678 type Key = u64;
1679
1680 fn key(&self) -> u64 {
1681 u64::from(u32::from(self.node))
1682 }
1683}
1684
1685impl BTreeEntryReadWrite for UnicodeNodeBTreeEntry {
1686 const ENTRY_SIZE: usize = 32;
1687
1688 fn read(f: &mut dyn Read) -> io::Result<Self> {
1689 let node = f.read_u64::<LittleEndian>()?;
1691 let Ok(node) = u32::try_from(node) else {
1692 return Err(NdbError::InvalidNodeBTreeEntryNodeId(node).into());
1693 };
1694 let node = NodeId::from(node);
1695
1696 let data = UnicodeBlockId::read(f)?;
1698
1699 let sub_node = UnicodeBlockId::read(f)?;
1701 let sub_node = if sub_node.search_key() == 0 {
1702 None
1703 } else {
1704 Some(sub_node)
1705 };
1706
1707 let parent = NodeId::read(f)?;
1709 let parent = if u32::from(parent) == 0 {
1710 None
1711 } else {
1712 Some(parent)
1713 };
1714
1715 let padding = f.read_u32::<LittleEndian>()?;
1717
1718 Ok(Self {
1719 node,
1720 data,
1721 sub_node,
1722 parent,
1723 padding,
1724 })
1725 }
1726
1727 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
1728 f.write_u64::<LittleEndian>(u64::from(u32::from(self.node)))?;
1730
1731 self.data.write(f)?;
1733
1734 self.sub_node.unwrap_or_default().write(f)?;
1736
1737 self.parent.unwrap_or_default().write(f)?;
1739
1740 f.write_u32::<LittleEndian>(self.padding)
1742 }
1743}
1744
1745impl NodeBTreeEntry for UnicodeNodeBTreeEntry {
1746 type Block = UnicodeBlockId;
1747
1748 fn node(&self) -> NodeId {
1749 self.node
1750 }
1751
1752 fn data(&self) -> UnicodeBlockId {
1753 self.data
1754 }
1755
1756 fn sub_node(&self) -> Option<UnicodeBlockId> {
1757 self.sub_node
1758 }
1759
1760 fn parent(&self) -> Option<NodeId> {
1761 self.parent
1762 }
1763}
1764
1765impl NodeBTreeEntryReadWrite for UnicodeNodeBTreeEntry {
1766 fn new(
1767 node: NodeId,
1768 data: UnicodeBlockId,
1769 sub_node: Option<UnicodeBlockId>,
1770 parent: Option<NodeId>,
1771 ) -> Self {
1772 Self::new(node, data, sub_node, parent)
1773 }
1774}
1775
1776pub struct UnicodeNodeBTreePage {
1777 max_entries: u8,
1778 entry_size: u8,
1779 entries: Vec<UnicodeNodeBTreeEntry>,
1780 trailer: UnicodePageTrailer,
1781}
1782
1783impl UnicodeNodeBTreePage {
1784 pub fn new(
1785 level: u8,
1786 max_entries: u8,
1787 entry_size: u8,
1788 entries: &[UnicodeNodeBTreeEntry],
1789 trailer: UnicodePageTrailer,
1790 ) -> NdbResult<Self> {
1791 if level != 0 {
1792 return Err(NdbError::InvalidBTreePageLevel(level));
1793 }
1794
1795 if entries.len() > usize::from(max_entries) {
1796 return Err(NdbError::InvalidBTreeEntryCount(entries.len()));
1797 }
1798
1799 if trailer.page_type() != PageType::NodeBTree {
1800 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
1801 }
1802
1803 let entries = entries.to_vec();
1804
1805 Ok(Self {
1806 max_entries,
1807 entry_size,
1808 entries,
1809 trailer,
1810 })
1811 }
1812}
1813
1814impl BTreePage for UnicodeNodeBTreePage {
1815 type Entry = UnicodeNodeBTreeEntry;
1816 type Trailer = UnicodePageTrailer;
1817
1818 fn level(&self) -> u8 {
1819 0
1820 }
1821
1822 fn entries(&self) -> &[UnicodeNodeBTreeEntry] {
1823 &self.entries
1824 }
1825
1826 fn trailer(&self) -> &UnicodePageTrailer {
1827 &self.trailer
1828 }
1829}
1830
1831impl BTreePageReadWrite for UnicodeNodeBTreePage {
1832 fn new(
1833 level: u8,
1834 max_entries: u8,
1835 entry_size: u8,
1836 entries: &[UnicodeNodeBTreeEntry],
1837 trailer: UnicodePageTrailer,
1838 ) -> NdbResult<Self> {
1839 Self::new(level, max_entries, entry_size, entries, trailer)
1840 }
1841
1842 fn max_entries(&self) -> u8 {
1843 self.max_entries
1844 }
1845
1846 fn entry_size(&self) -> u8 {
1847 self.entry_size
1848 }
1849}
1850
1851impl UnicodeBTreePageReadWrite<UnicodeNodeBTreeEntry> for UnicodeNodeBTreePage {}
1852
1853#[derive(Copy, Clone, Default, Debug)]
1854pub struct AnsiNodeBTreeEntry {
1855 node: NodeId,
1856 data: AnsiBlockId,
1857 sub_node: Option<AnsiBlockId>,
1858 parent: Option<NodeId>,
1859}
1860
1861impl AnsiNodeBTreeEntry {
1862 pub fn new(
1863 node: NodeId,
1864 data: AnsiBlockId,
1865 sub_node: Option<AnsiBlockId>,
1866 parent: Option<NodeId>,
1867 ) -> Self {
1868 Self {
1869 node,
1870 data,
1871 sub_node,
1872 parent,
1873 }
1874 }
1875}
1876
1877impl BTreeEntry for AnsiNodeBTreeEntry {
1878 type Key = u32;
1879
1880 fn key(&self) -> u32 {
1881 u32::from(self.node)
1882 }
1883}
1884
1885impl BTreeEntryReadWrite for AnsiNodeBTreeEntry {
1886 const ENTRY_SIZE: usize = 16;
1887
1888 fn read(f: &mut dyn Read) -> io::Result<Self> {
1889 let node = NodeId::read(f)?;
1891
1892 let data = AnsiBlockId::read(f)?;
1894
1895 let sub_node = AnsiBlockId::read(f)?;
1897 let sub_node = if sub_node.search_key() == 0 {
1898 None
1899 } else {
1900 Some(sub_node)
1901 };
1902
1903 let parent = NodeId::read(f)?;
1905 let parent = if u32::from(parent) == 0 {
1906 None
1907 } else {
1908 Some(parent)
1909 };
1910
1911 Ok(Self {
1912 node,
1913 data,
1914 sub_node,
1915 parent,
1916 })
1917 }
1918
1919 fn write(&self, f: &mut dyn Write) -> io::Result<()> {
1920 self.node.write(f)?;
1922
1923 self.data.write(f)?;
1925
1926 self.sub_node.unwrap_or_default().write(f)?;
1928
1929 self.parent.unwrap_or_default().write(f)
1931 }
1932}
1933
1934impl NodeBTreeEntry for AnsiNodeBTreeEntry {
1935 type Block = AnsiBlockId;
1936
1937 fn node(&self) -> NodeId {
1938 self.node
1939 }
1940
1941 fn data(&self) -> AnsiBlockId {
1942 self.data
1943 }
1944
1945 fn sub_node(&self) -> Option<AnsiBlockId> {
1946 self.sub_node
1947 }
1948
1949 fn parent(&self) -> Option<NodeId> {
1950 self.parent
1951 }
1952}
1953
1954impl NodeBTreeEntryReadWrite for AnsiNodeBTreeEntry {
1955 fn new(
1956 node: NodeId,
1957 data: AnsiBlockId,
1958 sub_node: Option<AnsiBlockId>,
1959 parent: Option<NodeId>,
1960 ) -> Self {
1961 Self::new(node, data, sub_node, parent)
1962 }
1963}
1964
1965pub struct AnsiNodeBTreePage {
1966 max_entries: u8,
1967 entry_size: u8,
1968 entries: Vec<AnsiNodeBTreeEntry>,
1969 trailer: AnsiPageTrailer,
1970}
1971
1972impl AnsiNodeBTreePage {
1973 pub fn new(
1974 level: u8,
1975 max_entries: u8,
1976 entry_size: u8,
1977 entries: &[AnsiNodeBTreeEntry],
1978 trailer: AnsiPageTrailer,
1979 ) -> NdbResult<Self> {
1980 if level != 0 {
1981 return Err(NdbError::InvalidBTreePageLevel(level));
1982 }
1983
1984 if entries.len() > usize::from(max_entries) {
1985 return Err(NdbError::InvalidBTreeEntryCount(entries.len()));
1986 }
1987
1988 if trailer.page_type() != PageType::NodeBTree {
1989 return Err(NdbError::UnexpectedPageType(trailer.page_type()));
1990 }
1991
1992 let entries = entries.to_vec();
1993
1994 Ok(Self {
1995 max_entries,
1996 entry_size,
1997 entries,
1998 trailer,
1999 })
2000 }
2001}
2002
2003impl BTreePage for AnsiNodeBTreePage {
2004 type Entry = AnsiNodeBTreeEntry;
2005 type Trailer = AnsiPageTrailer;
2006
2007 fn level(&self) -> u8 {
2008 0
2009 }
2010
2011 fn entries(&self) -> &[AnsiNodeBTreeEntry] {
2012 &self.entries
2013 }
2014
2015 fn trailer(&self) -> &AnsiPageTrailer {
2016 &self.trailer
2017 }
2018}
2019
2020impl BTreePageReadWrite for AnsiNodeBTreePage {
2021 fn new(
2022 level: u8,
2023 max_entries: u8,
2024 entry_size: u8,
2025 entries: &[AnsiNodeBTreeEntry],
2026 trailer: AnsiPageTrailer,
2027 ) -> NdbResult<Self> {
2028 Self::new(level, max_entries, entry_size, entries, trailer)
2029 }
2030
2031 fn max_entries(&self) -> u8 {
2032 self.max_entries
2033 }
2034
2035 fn entry_size(&self) -> u8 {
2036 self.entry_size
2037 }
2038}
2039
2040impl AnsiBTreePageReadWrite<AnsiNodeBTreeEntry> for AnsiNodeBTreePage {}
2041
2042pub trait RootBTreeIntermediatePage<Pst, Entry, LeafPage>
2043where
2044 Pst: PstFile,
2045 Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey>,
2046 LeafPage: RootBTreeLeafPage<Pst, Entry = Entry>,
2047 Self: BTreePage<
2048 Entry = <Self as RootBTreeIntermediatePage<Pst, Entry, LeafPage>>::Entry,
2049 Trailer = <Pst as PstFile>::PageTrailer,
2050 >,
2051{
2052 type Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey>
2053 + BTreePageEntry<Block = <Pst as PstFile>::PageRef>;
2054 type Page: BTreePageReadWrite<
2055 Entry = <Self as RootBTreeIntermediatePage<Pst, Entry, LeafPage>>::Entry,
2056 Trailer = <Pst as PstFile>::PageTrailer,
2057 >;
2058}
2059
2060impl<Entry, LeafPage> RootBTreeIntermediatePage<UnicodePstFile, Entry, LeafPage>
2061 for UnicodeBTreeEntryPage
2062where
2063 Entry: BTreeEntry<Key = u64> + BTreeEntryReadWrite,
2064 LeafPage: RootBTreeLeafPage<UnicodePstFile, Entry = Entry>,
2065{
2066 type Entry = UnicodeBTreePageEntry;
2067 type Page = UnicodeBTreeEntryPage;
2068}
2069
2070impl<Entry, LeafPage> RootBTreeIntermediatePageReadWrite<UnicodePstFile, Entry, LeafPage>
2071 for UnicodeBTreeEntryPage
2072where
2073 Entry: BTreeEntry<Key = u64> + BTreeEntryReadWrite,
2074 LeafPage: RootBTreeLeafPage<UnicodePstFile, Entry = Entry>
2075 + RootBTreeLeafPageReadWrite<UnicodePstFile>,
2076{
2077 fn read<R: PstReader>(f: &mut R) -> io::Result<Self> {
2078 <Self as UnicodeBTreePageReadWrite<UnicodeBTreePageEntry>>::read(f)
2079 }
2080
2081 fn write<W: Write + Seek>(&self, f: &mut W) -> io::Result<()> {
2082 <Self as UnicodeBTreePageReadWrite<UnicodeBTreePageEntry>>::write(self, f)
2083 }
2084}
2085
2086impl<Entry, LeafPage> RootBTreeIntermediatePage<AnsiPstFile, Entry, LeafPage> for AnsiBTreeEntryPage
2087where
2088 Entry: BTreeEntry<Key = u32> + BTreeEntryReadWrite,
2089 LeafPage: RootBTreeLeafPage<AnsiPstFile, Entry = Entry>,
2090{
2091 type Entry = AnsiBTreePageEntry;
2092 type Page = AnsiBTreeEntryPage;
2093}
2094
2095impl<Entry, LeafPage> RootBTreeIntermediatePageReadWrite<AnsiPstFile, Entry, LeafPage>
2096 for AnsiBTreeEntryPage
2097where
2098 Entry: BTreeEntry<Key = u32> + BTreeEntryReadWrite,
2099 LeafPage:
2100 RootBTreeLeafPage<AnsiPstFile, Entry = Entry> + RootBTreeLeafPageReadWrite<AnsiPstFile>,
2101{
2102 fn read<R: PstReader>(f: &mut R) -> io::Result<Self> {
2103 <Self as AnsiBTreePageReadWrite<AnsiBTreePageEntry>>::read(f)
2104 }
2105
2106 fn write<W: Write + Seek>(&self, f: &mut W) -> io::Result<()> {
2107 <Self as AnsiBTreePageReadWrite<AnsiBTreePageEntry>>::write(self, f)
2108 }
2109}
2110
2111pub trait RootBTreeLeafPage<Pst>
2112where
2113 Pst: PstFile,
2114 Self: BTreePage<
2115 Entry = <Self as RootBTreeLeafPage<Pst>>::Entry,
2116 Trailer = <Pst as PstFile>::PageTrailer,
2117 >,
2118{
2119 type Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey>;
2120}
2121
2122impl RootBTreeLeafPage<UnicodePstFile> for UnicodeBlockBTreePage {
2123 type Entry = UnicodeBlockBTreeEntry;
2124}
2125
2126impl RootBTreeLeafPageReadWrite<UnicodePstFile> for UnicodeBlockBTreePage {
2127 const BTREE_ENTRIES_SIZE: usize = UNICODE_BTREE_ENTRIES_SIZE;
2128
2129 fn read<R: PstReader>(f: &mut R) -> io::Result<Self> {
2130 <Self as UnicodeBTreePageReadWrite<UnicodeBlockBTreeEntry>>::read(f)
2131 }
2132
2133 fn write<W: Write + Seek>(&self, f: &mut W) -> io::Result<()> {
2134 <Self as UnicodeBTreePageReadWrite<UnicodeBlockBTreeEntry>>::write(self, f)
2135 }
2136}
2137
2138impl RootBTreeLeafPage<AnsiPstFile> for AnsiBlockBTreePage {
2139 type Entry = AnsiBlockBTreeEntry;
2140}
2141
2142impl RootBTreeLeafPageReadWrite<AnsiPstFile> for AnsiBlockBTreePage {
2143 const BTREE_ENTRIES_SIZE: usize = ANSI_BTREE_ENTRIES_SIZE;
2144
2145 fn read<R: PstReader>(f: &mut R) -> io::Result<Self> {
2146 <Self as AnsiBTreePageReadWrite<AnsiBlockBTreeEntry>>::read(f)
2147 }
2148
2149 fn write<W: Write + Seek>(&self, f: &mut W) -> io::Result<()> {
2150 <Self as AnsiBTreePageReadWrite<AnsiBlockBTreeEntry>>::write(self, f)
2151 }
2152}
2153
2154impl RootBTreeLeafPage<UnicodePstFile> for UnicodeNodeBTreePage {
2155 type Entry = UnicodeNodeBTreeEntry;
2156}
2157
2158impl RootBTreeLeafPageReadWrite<UnicodePstFile> for UnicodeNodeBTreePage {
2159 const BTREE_ENTRIES_SIZE: usize = UNICODE_BTREE_ENTRIES_SIZE;
2160
2161 fn read<R: PstReader>(f: &mut R) -> io::Result<Self> {
2162 <Self as UnicodeBTreePageReadWrite<UnicodeNodeBTreeEntry>>::read(f)
2163 }
2164
2165 fn write<W: Write + Seek>(&self, f: &mut W) -> io::Result<()> {
2166 <Self as UnicodeBTreePageReadWrite<UnicodeNodeBTreeEntry>>::write(self, f)
2167 }
2168}
2169
2170impl RootBTreeLeafPage<AnsiPstFile> for AnsiNodeBTreePage {
2171 type Entry = AnsiNodeBTreeEntry;
2172}
2173
2174impl RootBTreeLeafPageReadWrite<AnsiPstFile> for AnsiNodeBTreePage {
2175 const BTREE_ENTRIES_SIZE: usize = ANSI_BTREE_ENTRIES_SIZE;
2176
2177 fn read<R: PstReader>(f: &mut R) -> io::Result<Self> {
2178 <Self as AnsiBTreePageReadWrite<AnsiNodeBTreeEntry>>::read(f)
2179 }
2180
2181 fn write<W: Write + Seek>(&self, f: &mut W) -> io::Result<()> {
2182 <Self as AnsiBTreePageReadWrite<AnsiNodeBTreeEntry>>::write(self, f)
2183 }
2184}
2185
2186pub trait RootBTree {
2187 type Pst: PstFile<BTreeKey: BTreeEntryKey>;
2188 type Entry: BTreeEntry<Key = <Self::Pst as PstFile>::BTreeKey> + Sized;
2189 type IntermediatePage: RootBTreeIntermediatePage<Self::Pst, Self::Entry, Self::LeafPage>;
2190 type LeafPage: RootBTreeLeafPage<Self::Pst, Entry = Self::Entry>;
2191}
2192
2193pub enum RootBTreePage<Pst, Entry, IntermediatePage, LeafPage>
2194where
2195 Pst: PstFile,
2196 Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey>,
2197 IntermediatePage: RootBTreeIntermediatePage<Pst, Entry, LeafPage>,
2198 LeafPage: RootBTreeLeafPage<Pst, Entry = Entry>,
2199{
2200 Intermediate(Box<IntermediatePage>, PhantomData<(Pst, Entry)>),
2201 Leaf(Box<LeafPage>),
2202}
2203
2204impl<Pst, Entry, IntermediatePage, LeafPage> RootBTree
2205 for RootBTreePage<Pst, Entry, IntermediatePage, LeafPage>
2206where
2207 Pst: PstFile,
2208 Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey>,
2209 IntermediatePage: RootBTreeIntermediatePage<Pst, Entry, LeafPage>,
2210 LeafPage: RootBTreeLeafPage<Pst, Entry = Entry>,
2211{
2212 type Pst = Pst;
2213 type Entry = Entry;
2214 type IntermediatePage = IntermediatePage;
2215 type LeafPage = LeafPage;
2216}
2217
2218impl<Pst, Entry, IntermediatePage, LeafPage> RootBTreeReadWrite
2219 for RootBTreePage<Pst, Entry, IntermediatePage, LeafPage>
2220where
2221 Pst: PstFile,
2222 <Pst as PstFile>::BlockId: BlockIdReadWrite,
2223 <Pst as PstFile>::ByteIndex: ByteIndexReadWrite,
2224 <Pst as PstFile>::BlockRef: BlockRefReadWrite,
2225 <Pst as PstFile>::PageRef: BlockRefReadWrite,
2226 <Pst as PstFile>::PageTrailer: PageTrailerReadWrite,
2227 <Pst as PstFile>::BTreeKey: BTreePageKeyReadWrite + Into<u64>,
2228 Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey> + BTreeEntryReadWrite,
2229 IntermediatePage: RootBTreeIntermediatePage<Pst, Entry, LeafPage>,
2230 LeafPage: RootBTreeLeafPage<Pst, Entry = Entry>,
2231 <Self as RootBTree>::Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey> + BTreeEntryReadWrite,
2232 <Self as RootBTree>::IntermediatePage: RootBTreeIntermediatePageReadWrite<Pst, Entry, LeafPage>,
2233 <Self as RootBTree>::LeafPage: RootBTreeLeafPageReadWrite<Pst>,
2234{
2235 fn read<R: PstReader>(f: &mut R, block: <Pst as PstFile>::PageRef) -> io::Result<Self> {
2236 f.seek(SeekFrom::Start(block.index().index().into()))?;
2237
2238 let mut buffer = [0_u8; PAGE_SIZE];
2239 f.read_exact(&mut buffer)?;
2240 let mut cursor = Cursor::new(buffer);
2241
2242 cursor.seek(SeekFrom::Start(LeafPage::BTREE_ENTRIES_SIZE as u64 + 3))?;
2243 let level = cursor.read_u8()?;
2244
2245 cursor.seek(SeekFrom::Start(0))?;
2246 Ok(if level == 0 {
2247 Self::Leaf(Box::new(LeafPage::read(&mut cursor)?))
2248 } else {
2249 Self::Intermediate(Box::new(IntermediatePage::read(&mut cursor)?), PhantomData)
2250 })
2251 }
2252
2253 fn write<W: Write + Seek>(
2254 &self,
2255 f: &mut W,
2256 block: <Pst as PstFile>::PageRef,
2257 ) -> io::Result<()> {
2258 f.seek(SeekFrom::Start(block.index().index().into()))?;
2259
2260 match self {
2261 Self::Intermediate(page, ..) => page.write(f),
2262 Self::Leaf(page) => page.write(f),
2263 }
2264 }
2265
2266 fn find_entry<R: PstReader>(
2267 &self,
2268 f: &mut R,
2269 key: <Pst as PstFile>::BTreeKey,
2270 page_cache: &mut RootBTreePageCache<Self>,
2271 ) -> io::Result<Entry> {
2272 let search_key: u64 = key.into();
2273 match self {
2274 Self::Intermediate(page, ..) => {
2275 let entries = <Self::IntermediatePage as BTreePage>::entries(page);
2276 let index = entries.partition_point(|entry| entry.key().into() <= search_key);
2277 let entry = index
2278 .checked_sub(1)
2279 .and_then(|index| entries.get(index))
2280 .ok_or(NdbError::BTreePageNotFound(search_key))?;
2281 let block = entry.block();
2282 let page = match page_cache.remove(&block.block()) {
2283 Some(page) => page,
2284 None => <Self as RootBTreeReadWrite>::read(f, block)?,
2285 };
2286 let entry = page.find_entry(f, key, page_cache);
2287 page_cache.insert(block.block(), page);
2288 entry
2289 }
2290 Self::Leaf(page) => {
2291 let entry = <Self::LeafPage as BTreePage>::entries(page)
2292 .iter()
2293 .find(|entry| entry.key().into() == search_key)
2294 .ok_or(NdbError::BTreePageNotFound(search_key))?;
2295 Ok(*entry)
2296 }
2297 }
2298 }
2299}
2300
2301impl<Pst, Entry, IntermediatePage, LeafPage> RootBTreePage<Pst, Entry, IntermediatePage, LeafPage>
2302where
2303 Pst: PstFile,
2304 <Pst as PstFile>::BlockId: BlockIdReadWrite,
2305 <Pst as PstFile>::ByteIndex: ByteIndexReadWrite,
2306 <Pst as PstFile>::BlockRef: BlockRefReadWrite,
2307 <Pst as PstFile>::PageRef: BlockRefReadWrite,
2308 <Pst as PstFile>::PageTrailer: PageTrailerReadWrite,
2309 <Pst as PstFile>::BTreeKey: BTreePageKeyReadWrite + Into<u64>,
2310 Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey> + BTreeEntryReadWrite,
2311 IntermediatePage: RootBTreeIntermediatePage<Pst, Entry, LeafPage>,
2312 LeafPage: RootBTreeLeafPage<Pst, Entry = Entry>,
2313 <Self as RootBTree>::Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey> + BTreeEntryReadWrite,
2314 <Self as RootBTree>::IntermediatePage: RootBTreeIntermediatePageReadWrite<Pst, Entry, LeafPage>,
2315 <Self as RootBTree>::LeafPage: RootBTreeLeafPageReadWrite<Pst>,
2316{
2317 pub fn read<R: PstReader>(f: &mut R, block: <Pst as PstFile>::PageRef) -> io::Result<Self> {
2318 <Self as RootBTreeReadWrite>::read(f, block)
2319 }
2320
2321 pub fn write<W: Write + Seek>(
2322 &self,
2323 f: &mut W,
2324 block: <Pst as PstFile>::PageRef,
2325 ) -> io::Result<()> {
2326 <Self as RootBTreeReadWrite>::write(self, f, block)
2327 }
2328
2329 pub fn find_entry<R: PstReader>(
2330 &self,
2331 f: &mut R,
2332 key: <Pst as PstFile>::BTreeKey,
2333 page_cache: &mut RootBTreePageCache<Self>,
2334 ) -> io::Result<Entry> {
2335 <Self as RootBTreeReadWrite>::find_entry(self, f, key, page_cache)
2336 }
2337}
2338
2339pub type UnicodeBTree<Entry, LeafPage> =
2340 RootBTreePage<UnicodePstFile, Entry, UnicodeBTreeEntryPage, LeafPage>;
2341
2342pub type AnsiBTree<Entry, LeafPage> =
2343 RootBTreePage<AnsiPstFile, Entry, AnsiBTreeEntryPage, LeafPage>;
2344
2345pub trait BlockBTree<Pst, Entry>: RootBTree<Pst = Pst, Entry = Entry>
2346where
2347 Pst: PstFile,
2348 Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey>
2349 + BlockBTreeEntry<Block = <Pst as PstFile>::BlockRef>,
2350 <Self as RootBTree>::IntermediatePage:
2351 RootBTreeIntermediatePage<Pst, Entry, <Self as RootBTree>::LeafPage>,
2352 <Self as RootBTree>::LeafPage: RootBTreeLeafPage<Pst, Entry = <Self as RootBTree>::Entry>,
2353{
2354}
2355
2356pub type UnicodeBlockBTree = UnicodeBTree<UnicodeBlockBTreeEntry, UnicodeBlockBTreePage>;
2357impl BlockBTree<UnicodePstFile, UnicodeBlockBTreeEntry> for UnicodeBlockBTree {}
2358impl BlockBTreeReadWrite<UnicodePstFile, UnicodeBlockBTreeEntry> for UnicodeBlockBTree {}
2359
2360pub type AnsiBlockBTree = AnsiBTree<AnsiBlockBTreeEntry, AnsiBlockBTreePage>;
2361impl BlockBTree<AnsiPstFile, AnsiBlockBTreeEntry> for AnsiBlockBTree {}
2362impl BlockBTreeReadWrite<AnsiPstFile, AnsiBlockBTreeEntry> for AnsiBlockBTree {}
2363
2364pub trait NodeBTree<Pst, Entry>: RootBTree<Pst = Pst, Entry = Entry>
2365where
2366 Pst: PstFile,
2367 Entry: BTreeEntry<Key = <Pst as PstFile>::BTreeKey>
2368 + NodeBTreeEntry<Block = <Pst as PstFile>::BlockId>,
2369 <Self as RootBTree>::IntermediatePage:
2370 RootBTreeIntermediatePage<Pst, Entry, <Self as RootBTree>::LeafPage>,
2371 <Self as RootBTree>::LeafPage: RootBTreeLeafPage<Pst, Entry = <Self as RootBTree>::Entry>,
2372{
2373}
2374
2375pub type UnicodeNodeBTree = UnicodeBTree<UnicodeNodeBTreeEntry, UnicodeNodeBTreePage>;
2376impl NodeBTree<UnicodePstFile, UnicodeNodeBTreeEntry> for UnicodeNodeBTree {}
2377impl NodeBTreeReadWrite<UnicodePstFile, UnicodeNodeBTreeEntry> for UnicodeNodeBTree {}
2378
2379pub type AnsiNodeBTree = AnsiBTree<AnsiNodeBTreeEntry, AnsiNodeBTreePage>;
2380impl NodeBTree<AnsiPstFile, AnsiNodeBTreeEntry> for AnsiNodeBTree {}
2381impl NodeBTreeReadWrite<AnsiPstFile, AnsiNodeBTreeEntry> for AnsiNodeBTree {}