1use std::marker::PhantomData;
2use crate::errors::{Error,Result};
3use crate::common::{ByteIter,SHType,Layout,Width};
4use crate::tables::{TableItem,StringItem,RelaItem,RelItem,ArrayItem};
5use crate::symbols::Symbol;
6use crate::Section;
7
8pub type Array<'a> = Table<'a,ArrayItem>;
9pub type ArrayMut<'a> = TableMut<'a,ArrayItem>;
10
11pub type SymbolTable<'a> = Table<'a,Symbol>;
12pub type SymbolTableMut<'a> = TableMut<'a,Symbol>;
13
14pub type RelTable<'a> = Table<'a,RelItem>;
15pub type RelTableMut<'a> = TableMut<'a,RelItem>;
16
17pub type RelaTable<'a> = Table<'a,RelaItem>;
18pub type RelaTableMut<'a> = TableMut<'a,RelaItem>;
19
20pub type StringTable<'a> = Table<'a,StringItem>;
21pub type StringTableMut<'a> = TableMut<'a,StringItem>;
22
23pub trait TableView<T>
25where
26 T: TableItem + Default
27{
28 fn section(&self) -> &Section;
30
31 fn name_index(&self) -> usize {
33 self.section().name_index()
34 }
35
36 fn iterator(&self) -> ByteIter {
38 ByteIter::new(
39 self.section().data(),
40 T::delimiter(
41 self.section().entity_size()))
42 }
43
44 fn data(&self, index: usize) -> Result<&[u8]> {
46 self.iterator()
47 .nth(index)
48 .ok_or(Error::OutOfBoundsError)
49 }
50
51 fn offset(&self, index: usize) -> usize {
53 if self.has_fixed_size() {
54 self.section().entity_size() * index
55 } else {
56 self.iterator()
57 .enumerate()
58 .take_while(|(i,_)| i < &index)
59 .fold(0,|a,(_,e)| a + e.len())
60 }
61 }
62
63 fn at(&self, index: usize) -> Result<T> {
65 T::parse(self.data(index)?,self.section())
66 }
67
68 fn at_offset(&self, offset: usize) -> Result<T> {
70 self.iterator()
71 .offset(offset)
72 .next()
73 .ok_or(Error::OutOfBoundsError)
74 .and_then(|d| T::parse(d,self.section()))
75 }
76
77 fn items(&self) -> Result<Vec<T>> {
79 self.iterator()
80 .map(|b| T::parse(b,self.section()))
81 .collect()
82 }
83
84 fn len(&self) -> usize {
86 if self.has_fixed_size() {
87 self.section().entity_count()
88 } else {
89 self.iterator().count()
90 }
91 }
92
93 fn size(&self) -> usize {
95 self.section().body_size()
96 }
97
98 fn layout(&self) -> Layout {
100 self.section().layout()
101 }
102
103 fn width(&self) -> Width {
105 self.section().width()
106 }
107
108 fn has_fixed_size(&self) -> bool {
110 self.section().entity_size() > 0
111 }
112
113 fn has_variable_size(&self) -> bool {
115 !self.has_fixed_size()
116 }
117
118}
119
120pub struct Table<'a,T>
122where
123 T: TableItem + Default
124{
125 item: PhantomData<T>,
126 section: &'a Section
127}
128
129pub struct TableMut<'a,T>
131where
132 T: TableItem + Default
133{
134 item: PhantomData<T>,
135 section: &'a mut Section
136}
137
138impl<'a,T> Table<'a,T>
139where
140 T: TableItem + Default
141{
142 fn new(section: &'a Section) -> Self {
144 Self {
145 item: PhantomData {},
146 section,
147 }
148 }
149}
150
151impl<'a,T> TableView<T> for Table<'a,T>
152where
153 T: TableItem + Default
154{
155 fn section(&self) -> &Section {
156 self.section
157 }
158}
159
160impl<'a,T> TableMut<'a,T>
161where
162 T: TableItem + Default
163{
164
165 fn new(section: &'a mut Section) -> Self {
167 Self {
168 item: PhantomData {},
169 section: section,
170 }
171 }
172
173 fn reserve(&mut self, offset: usize, size: usize) {
175 let length = self.size() + size;
176
177 self.section
178 .data_mut()
179 .splice(offset..offset,(0..size).map(|_| 0));
180
181 self.section
182 .set_body_size(length);
183 }
184
185 fn discard(&mut self, offset: usize, size: usize) {
187 let length = self.size() - size;
188
189 self.section
190 .data_mut()
191 .drain(offset..offset + size);
192
193 self.section
194 .set_body_size(length);
195 }
196
197 pub fn append(&mut self, item: T) -> Result<usize> {
199 self.insert(self.len(),item)
200 }
201
202 pub fn prepend(&mut self, item: T) -> Result<usize> {
204 self.insert(0,item)
205 }
206
207 pub fn insert(&mut self, index: usize, mut item: T) -> Result<usize> {
209 item.set_layout(self.layout());
210 item.set_width(self.width());
211
212 let size = item.size();
213 let offset = self.offset(index);
214
215 self.reserve(offset,size);
217
218 let data = self.section.slice_mut(offset,size)?;
220
221 item.write(data)?;
223
224 Ok(size)
225 }
226
227 pub fn remove(&mut self, index: usize) -> Result<T> {
229 let data = self.data(index)?;
230 let offset = self.offset(index);
231 let size = data.len();
232
233 let item = T::parse(data,&self.section)?;
234
235 self.discard(offset,size);
237
238 Ok(item)
239 }
240
241}
242
243impl<'a,T> TableView<T> for TableMut<'a,T>
244where
245 T: TableItem + Default
246{
247 fn section(&self) -> &Section {
248 self.section
249 }
250}
251
252impl<'a> TryFrom<&'a Section> for Table<'a, Symbol>
253{
254 type Error = Error;
255
256 fn try_from(section: &'a Section) -> Result<Self> {
257 match section.header().kind() {
258 SHType::SHT_SYMTAB => Ok(Self::new(section)),
259 SHType::SHT_DYNSYM => Ok(Self::new(section)),
260 _ => Err(Error::WrongSectionError)
261 }
262 }
263}
264
265impl<'a> TryFrom<&'a mut Section> for TableMut<'a, Symbol>
266{
267 type Error = Error;
268
269 fn try_from(section: &'a mut Section) -> Result<Self> {
270 match section.header().kind() {
271 SHType::SHT_SYMTAB => Ok(Self::new(section)),
272 SHType::SHT_DYNSYM => Ok(Self::new(section)),
273 _ => Err(Error::WrongSectionError)
274 }
275 }
276}
277
278impl<'a> TryFrom<&'a Section> for Table<'a, StringItem>
279{
280 type Error = Error;
281
282 fn try_from(section: &'a Section) -> Result<Self> {
283 match section.header().kind() {
284 SHType::SHT_STRTAB => Ok(Self::new(section)),
285 _ => Err(Error::WrongSectionError)
286 }
287 }
288}
289
290impl<'a> TryFrom<&'a mut Section> for TableMut<'a, StringItem>
291{
292 type Error = Error;
293
294 fn try_from(section: &'a mut Section) -> Result<Self> {
295 match section.header().kind() {
296 SHType::SHT_STRTAB => Ok(Self::new(section)),
297 _ => Err(Error::WrongSectionError)
298 }
299 }
300}
301
302impl<'a> TryFrom<&'a Section> for Table<'a, RelaItem>
303{
304 type Error = Error;
305
306 fn try_from(section: &'a Section) -> Result<Self> {
307 match section.header().kind() {
308 SHType::SHT_RELA => Ok(Self::new(section)),
309 _ => Err(Error::WrongSectionError)
310 }
311 }
312}
313
314impl<'a> TryFrom<&'a mut Section> for TableMut<'a, RelaItem>
315{
316 type Error = Error;
317
318 fn try_from(section: &'a mut Section) -> Result<Self> {
319 match section.header().kind() {
320 SHType::SHT_RELA => Ok(Self::new(section)),
321 _ => Err(Error::WrongSectionError)
322 }
323 }
324}
325
326impl<'a> TryFrom<&'a Section> for Table<'a, RelItem>
327{
328 type Error = Error;
329
330 fn try_from(section: &'a Section) -> Result<Self> {
331 match section.header().kind() {
332 SHType::SHT_REL => Ok(Self::new(section)),
333 _ => Err(Error::WrongSectionError)
334 }
335 }
336}
337
338impl<'a> TryFrom<&'a mut Section> for TableMut<'a, RelItem>
339{
340 type Error = Error;
341
342 fn try_from(section: &'a mut Section) -> Result<Self> {
343 match section.header().kind() {
344 SHType::SHT_REL => Ok(Self::new(section)),
345 _ => Err(Error::WrongSectionError)
346 }
347 }
348}
349
350impl<'a> TryFrom<&'a Section> for Table<'a, ArrayItem>
351{
352 type Error = Error;
353
354 fn try_from(section: &'a Section) -> Result<Self> {
355 match section.header().kind() {
356 SHType::SHT_INIT_ARRAY | SHType::SHT_PREINIT_ARRAY | SHType::SHT_FINI_ARRAY => Ok(Self::new(section)),
357 _ => Err(Error::WrongSectionError)
358 }
359 }
360}
361
362impl<'a> TryFrom<&'a mut Section> for TableMut<'a, ArrayItem>
363{
364 type Error = Error;
365
366 fn try_from(section: &'a mut Section) -> Result<Self> {
367 match section.header().kind() {
368 SHType::SHT_INIT_ARRAY | SHType::SHT_PREINIT_ARRAY | SHType::SHT_FINI_ARRAY => Ok(Self::new(section)),
369 _ => Err(Error::WrongSectionError)
370 }
371 }
372}
373
374impl<'a,T> From<TableMut<'a,T>> for Table<'a,T>
375where
376 T: TableItem + Default
377{
378 fn from(table: TableMut<'a,T>) -> Self {
379 Self::new(table.section)
380 }
381}
382
383impl<'a,T> From<TableMut<'a,T>> for &'a mut Section
384where
385 T: TableItem + Default
386{
387 fn from(table: TableMut<'a,T>) -> Self {
388 table.section
389 }
390}
391
392impl<'a,T> From<Table<'a,T>> for &'a Section
393where
394 T: TableItem + Default
395{
396 fn from(table: Table<'a,T>) -> Self {
397 table.section
398 }
399}
400
401#[cfg(test)]
402mod tests {
403 use super::*;
404 use crate::headers::FileHeader;
405 use crate::utilities::read;
406
407 use crate::utilities::tests::{
408 LIBJPEG_DYNSYM as SYM_TEST,
409 LIBVPF_SHSTRTAB as STR_TEST,
410 LIBVPF_RELA_DYN as RELA_TEST,
411 LIBQSCINTILLA_FINI_ARRAY as FINI_TEST,
412 LIBQSCINTILLA_INIT_ARRAY as INIT_TEST,
413 };
414
415 macro_rules! section {
416 ( $path: expr, $index: expr ) => {
417 read($path)
418 .and_then(|d| FileHeader::parse(&d)
419 .and_then(|h| Ok((d,h))))
420 .and_then(|(d,h)|
421 Section::read_all(
422 &d,
423 h.shnum(),
424 h.shoff(),
425 h.shentsize(),
426 h.data(),
427 h.class()
428 )
429 )
430 .and_then(|s| s
431 .get($index)
432 .ok_or(Error::NotFound)
433 .cloned())
434 .expect("Section not found")
435 };
436 }
437
438 #[test]
439 fn test_read_symbols_as_table() {
440 let section = section!("assets/libjpeg/libjpeg.so.9", SYM_TEST.index);
441
442 let result = SymbolTable::try_from(§ion);
443 assert!(result.is_ok());
444
445 let table = result.unwrap();
446 assert_eq!(table.len(),SYM_TEST.length);
447 }
448
449 #[test]
450 fn test_read_strings_as_table() {
451 let section = section!("assets/libvpf/libvpf.so.4.1", STR_TEST.index);
452
453 let result = StringTable::try_from(§ion);
454 assert!(result.is_ok());
455
456 let table = result.unwrap();
457 assert_eq!(table.len(),STR_TEST.length);
458 }
459
460 #[test]
461 fn test_read_relocations_addend_as_table() {
462 let section = section!("assets/libvpf/libvpf.so.4.1", RELA_TEST.index);
463
464 let result = RelaTable::try_from(§ion);
465 assert!(result.is_ok());
466
467 let table = result.unwrap();
468 assert_eq!(table.len(),RELA_TEST.length);
469 }
470
471 #[test]
472 fn test_write_strings_prepend() {
473 let mut section = section!("assets/libvpf/libvpf.so.4.1", STR_TEST.index);
474
475 let result = StringTableMut::try_from(&mut section);
476 assert!(result.is_ok());
477
478 let mut table = result.unwrap();
479
480 assert_eq!(table.len(),STR_TEST.length);
481 assert_eq!(table.size(),STR_TEST.size);
482
483 let result = table.prepend("TEST".try_into().unwrap());
484 assert!(result.is_ok());
485
486 assert_eq!(table.len(),STR_TEST.length + 1);
487 assert_eq!(table.size(),STR_TEST.size + 5);
488
489 let result = table.at(0);
490 assert!(result.is_ok());
491
492 let item = result.unwrap();
493
494 let result = item.string();
495 assert!(result.is_ok());
496
497 let value = result.unwrap();
498 assert_eq!(value,"TEST".to_string());
499 }
500
501 #[test]
502 fn test_write_strings_append() {
503 let mut section = section!("assets/libvpf/libvpf.so.4.1", STR_TEST.index);
504
505 let result = StringTableMut::try_from(&mut section);
506 assert!(result.is_ok());
507
508 let mut table = result.unwrap();
509
510 assert_eq!(table.len(),STR_TEST.length);
511 assert_eq!(table.size(),STR_TEST.size);
512
513 let result = table.append("TEST".try_into().unwrap());
514 assert!(result.is_ok());
515
516 assert_eq!(table.len(),STR_TEST.length + 1);
517 assert_eq!(table.size(),STR_TEST.size + 5);
518
519 let result = table.at(table.len() - 1);
520 assert!(result.is_ok());
521
522 let item = result.unwrap();
523
524 let result = item.string();
525 assert!(result.is_ok());
526
527 let string = result.unwrap();
528 let value = string.as_str();
529 assert_eq!(value,"TEST");
530 }
531
532 #[test]
533 fn test_write_strings_insert() {
534 let mut section = section!("assets/libvpf/libvpf.so.4.1", STR_TEST.index);
535
536 let result = StringTableMut::try_from(&mut section);
537 assert!(result.is_ok());
538
539 let mut table = result.unwrap();
540
541 assert_eq!(table.len(),STR_TEST.length);
542 assert_eq!(table.size(),STR_TEST.size);
543
544 let result = table.insert(1,"TEST".try_into().unwrap());
545 assert!(result.is_ok());
546
547 assert_eq!(table.len(),STR_TEST.length + 1);
548 assert_eq!(table.size(),STR_TEST.size + 5);
549
550 let result = table.at(1);
551 assert!(result.is_ok());
552
553 let item = result.unwrap();
554
555 let result = item.string();
556 assert!(result.is_ok());
557
558 let string = result.unwrap();
559 let value = string.as_str();
560 assert_eq!(value,"TEST");
561 }
562
563 #[test]
564 fn test_write_strings_remove() {
565 let mut section = section!("assets/libvpf/libvpf.so.4.1", STR_TEST.index);
566
567 let result = StringTableMut::try_from(&mut section);
568 assert!(result.is_ok());
569
570 let mut table = result.unwrap();
571
572 assert_eq!(table.len(),STR_TEST.length);
573 assert_eq!(table.size(),STR_TEST.size);
574
575 let result = table.remove(1);
576 assert!(result.is_ok());
577
578 assert_eq!(table.len(),STR_TEST.length - 1);
579 assert_eq!(table.size(),STR_TEST.size - 10);
580
581 let result = table.at(1);
582 assert!(result.is_ok());
583
584 let item = result.unwrap();
585
586 let result = item.string();
587 assert!(result.is_ok());
588
589 let string = result.unwrap();
590 let value = string.as_str();
591 assert_ne!(value,".shstrtab");
592 }
593
594 #[test]
595 fn test_write_symbols_prepend() {
596 let mut section = section!("assets/libjpeg/libjpeg.so.9", SYM_TEST.index);
597
598 let result = SymbolTableMut::try_from(&mut section);
599 assert!(result.is_ok());
600
601 let mut table = result.unwrap();
602
603 assert_eq!(table.len(),SYM_TEST.length);
604 assert_eq!(table.size(),SYM_TEST.size);
605
606 let item1 = Symbol::default();
607
608 let result = table.prepend(item1.clone());
609 assert!(result.is_ok());
610
611 assert_eq!(table.len(),SYM_TEST.length + 1);
612 assert_eq!(table.size(),SYM_TEST.size + SYM_TEST.entsize);
613
614 let result = table.at(0);
615 assert!(result.is_ok());
616
617 let item2 = result.unwrap();
618 assert_eq!(item2.name(),item1.name());
619 assert_eq!(item2.value(),item1.value());
620 assert_eq!(item2.size(),item1.size());
621 assert_eq!(item2.other(),item1.other());
622 assert_eq!(item2.shndx(),item1.shndx());
623 }
624
625 #[test]
626 fn test_write_symbols_append() {
627 let mut section = section!("assets/libjpeg/libjpeg.so.9", SYM_TEST.index);
628
629 let result = SymbolTableMut::try_from(&mut section);
630 assert!(result.is_ok());
631
632 let mut table = result.unwrap();
633
634 assert_eq!(table.len(),SYM_TEST.length);
635 assert_eq!(table.size(),SYM_TEST.size);
636
637 let item1 = Symbol::default();
638
639 let result = table.append(item1.clone());
640 assert!(result.is_ok());
641
642 assert_eq!(table.len(),SYM_TEST.length + 1);
643 assert_eq!(table.size(),SYM_TEST.size + SYM_TEST.entsize);
644
645 let result = table.at(table.len() - 1);
646 assert!(result.is_ok());
647
648 let item2 = result.unwrap();
649 assert_eq!(item2.name(),item1.name());
650 assert_eq!(item2.value(),item1.value());
651 assert_eq!(item2.size(),item1.size());
652 assert_eq!(item2.other(),item1.other());
653 assert_eq!(item2.shndx(),item1.shndx());
654 }
655
656 #[test]
657 fn test_write_symbols_insert() {
658 let mut section = section!("assets/libjpeg/libjpeg.so.9", SYM_TEST.index);
659
660 let result = SymbolTableMut::try_from(&mut section);
661 assert!(result.is_ok());
662
663 let mut table = result.unwrap();
664
665 assert_eq!(table.len(),SYM_TEST.length);
666 assert_eq!(table.size(),SYM_TEST.size);
667
668 let item1 = Symbol::default();
669
670 let result = table.insert(3,item1.clone());
671 assert!(result.is_ok());
672
673 assert_eq!(table.len(),SYM_TEST.length + 1);
674 assert_eq!(table.size(),SYM_TEST.size + SYM_TEST.entsize);
675
676 let result = table.at(3);
677 assert!(result.is_ok());
678
679 let item2 = result.unwrap();
680 assert_eq!(item2.name(),item1.name());
681 assert_eq!(item2.value(),item1.value());
682 assert_eq!(item2.size(),item1.size());
683 assert_eq!(item2.other(),item1.other());
684 assert_eq!(item2.shndx(),item1.shndx());
685 }
686
687 #[test]
688 fn test_write_symbols_remove() {
689 let mut section = section!("assets/libjpeg/libjpeg.so.9", SYM_TEST.index);
690
691 let result = SymbolTableMut::try_from(&mut section);
692 assert!(result.is_ok());
693
694 let mut table = result.unwrap();
695
696 assert_eq!(table.len(),SYM_TEST.length);
697 assert_eq!(table.size(),SYM_TEST.size);
698
699 let result = table.remove(3);
700 assert!(result.is_ok());
701
702 assert_eq!(table.len(),SYM_TEST.length - 1);
703 assert_eq!(table.size(),SYM_TEST.size - SYM_TEST.entsize);
704 }
705
706 #[test]
707 fn test_write_relocations_addend_prepend() {
708 let mut section = section!("assets/libvpf/libvpf.so.4.1", RELA_TEST.index);
709
710 let result = RelaTableMut::try_from(&mut section);
711 assert!(result.is_ok());
712
713 let mut table = result.unwrap();
714
715 assert_eq!(table.len(),RELA_TEST.length);
716 assert_eq!(table.size(),RELA_TEST.size);
717
718 let item1 = RelaItem::default();
719
720 let result = table.prepend(item1.clone());
721 assert!(result.is_ok());
722
723 assert_eq!(table.len(),RELA_TEST.length + 1);
724 assert_eq!(table.size(),RELA_TEST.size + RELA_TEST.entsize);
725
726 let result = table.at(0);
727 assert!(result.is_ok());
728
729 let item2 = result.unwrap();
730 assert_eq!(item2.offset(),item1.offset());
731 assert_eq!(item2.info(),item1.info());
732 }
733
734 #[test]
735 fn test_write_relocations_addend_append() {
736 let mut section = section!("assets/libvpf/libvpf.so.4.1", RELA_TEST.index);
737
738 let result = RelaTableMut::try_from(&mut section);
739 assert!(result.is_ok());
740
741 let mut table = result.unwrap();
742
743 assert_eq!(table.len(),RELA_TEST.length);
744 assert_eq!(table.size(),RELA_TEST.size);
745
746 let item1 = RelaItem::default();
747
748 let result = table.append(item1.clone());
749 assert!(result.is_ok());
750
751 assert_eq!(table.len(),RELA_TEST.length + 1);
752 assert_eq!(table.size(),RELA_TEST.size + RELA_TEST.entsize);
753
754 let result = table.at(table.len() - 1);
755 assert!(result.is_ok());
756
757 let item2 = result.unwrap();
758 assert_eq!(item2.offset(),item1.offset());
759 assert_eq!(item2.info(),item1.info());
760 }
761
762 #[test]
763 fn test_write_relocations_addend_insert() {
764 let mut section = section!("assets/libvpf/libvpf.so.4.1", RELA_TEST.index);
765
766 let result = RelaTableMut::try_from(&mut section);
767 assert!(result.is_ok());
768
769 let mut table = result.unwrap();
770
771 assert_eq!(table.len(),RELA_TEST.length);
772 assert_eq!(table.size(),RELA_TEST.size);
773
774 let item1 = RelaItem::default();
775
776 let result = table.insert(3,item1.clone());
777 assert!(result.is_ok());
778
779 assert_eq!(table.len(),RELA_TEST.length + 1);
780 assert_eq!(table.size(),RELA_TEST.size + RELA_TEST.entsize);
781
782 let result = table.at(3);
783 assert!(result.is_ok());
784
785 let item2 = result.unwrap();
786 assert_eq!(item2.offset(),item1.offset());
787 assert_eq!(item2.info(),item1.info());
788 }
789
790 #[test]
791 fn test_write_relocations_addend_remove() {
792 let mut section = section!("assets/libvpf/libvpf.so.4.1", RELA_TEST.index);
793
794 let result = RelaTableMut::try_from(&mut section);
795 assert!(result.is_ok());
796
797 let mut table = result.unwrap();
798
799 assert_eq!(table.len(),RELA_TEST.length);
800 assert_eq!(table.size(),RELA_TEST.size);
801
802 let result = table.remove(3);
803 assert!(result.is_ok());
804
805 assert_eq!(table.len(),RELA_TEST.length - 1);
806 assert_eq!(table.size(),RELA_TEST.size - RELA_TEST.entsize);
807 }
808
809 #[test]
810 fn test_read_init_array_as_array() {
811 let section = section!("assets/libqscintilla2/libqscintilla2_qt5.so.15.0.0", INIT_TEST.index);
812
813 let result = Array::try_from(§ion);
814 assert!(result.is_ok());
815
816 let array = result.unwrap();
817 assert_eq!(array.len(),INIT_TEST.length);
818 }
819
820 #[test]
821 fn test_read_fini_array_as_array() {
822 let section = section!("assets/libqscintilla2/libqscintilla2_qt5.so.15.0.0", FINI_TEST.index);
823
824 let result = Array::try_from(§ion);
825 assert!(result.is_ok());
826
827 let array = result.unwrap();
828 assert_eq!(array.len(),FINI_TEST.length);
829 }
830
831 #[test]
832 fn test_write_init_array_append() {
833 let mut section = section!("assets/libqscintilla2/libqscintilla2_qt5.so.15.0.0", INIT_TEST.index);
834
835 let result = ArrayMut::try_from(&mut section);
836 assert!(result.is_ok());
837
838 let mut array = result.unwrap();
839
840 assert_eq!(array.len(),INIT_TEST.length);
841 assert_eq!(array.size(),INIT_TEST.size);
842
843 let result = array.append(123.into());
844 assert!(result.is_ok());
845
846 assert_eq!(array.len(),INIT_TEST.length + 1);
847 assert_eq!(array.size(),INIT_TEST.size + INIT_TEST.entsize);
848
849 let result = array.at(array.len() - 1);
850 assert!(result.is_ok());
851
852 let item = result.unwrap();
853 assert_eq!(item.value(),123);
854 }
855
856 #[test]
857 fn test_write_fini_array_append() {
858 let mut section = section!("assets/libqscintilla2/libqscintilla2_qt5.so.15.0.0", FINI_TEST.index);
859
860 let result = ArrayMut::try_from(&mut section);
861 assert!(result.is_ok());
862
863 let mut array = result.unwrap();
864
865 assert_eq!(array.len(),FINI_TEST.length);
866 assert_eq!(array.size(),FINI_TEST.size);
867
868 let result = array.append(123.into());
869 assert!(result.is_ok());
870
871 assert_eq!(array.len(),FINI_TEST.length + 1);
872 assert_eq!(array.size(),FINI_TEST.size + FINI_TEST.entsize);
873
874 let result = array.at(array.len() - 1);
875 assert!(result.is_ok());
876
877 let item = result.unwrap();
878 assert_eq!(item.value(),123);
879 }
880
881 #[test]
882 fn test_write_init_array_prepend() {
883 let mut section = section!("assets/libqscintilla2/libqscintilla2_qt5.so.15.0.0", INIT_TEST.index);
884
885 let result = ArrayMut::try_from(&mut section);
886 assert!(result.is_ok());
887
888 let mut array = result.unwrap();
889
890 assert_eq!(array.len(),INIT_TEST.length);
891 assert_eq!(array.size(),INIT_TEST.size);
892
893 let result = array.prepend(123.into());
894 assert!(result.is_ok());
895
896 assert_eq!(array.len(),INIT_TEST.length + 1);
897 assert_eq!(array.size(),INIT_TEST.size + INIT_TEST.entsize);
898
899 let result = array.at(0);
900 assert!(result.is_ok());
901
902 let item = result.unwrap();
903 assert_eq!(item.value(),123);
904 }
905
906 #[test]
907 fn test_write_fini_array_prepend() {
908 let mut section = section!("assets/libqscintilla2/libqscintilla2_qt5.so.15.0.0", FINI_TEST.index);
909
910 let result = ArrayMut::try_from(&mut section);
911 assert!(result.is_ok());
912
913 let mut array = result.unwrap();
914
915 assert_eq!(array.len(),FINI_TEST.length);
916 assert_eq!(array.size(),FINI_TEST.size);
917
918 let result = array.prepend(123.into());
919 assert!(result.is_ok());
920
921 assert_eq!(array.len(),FINI_TEST.length + 1);
922 assert_eq!(array.size(),FINI_TEST.size + FINI_TEST.entsize);
923
924 let result = array.at(0);
925 assert!(result.is_ok());
926
927 let item = result.unwrap();
928 assert_eq!(item.value(),123);
929 }
930
931 #[test]
932 fn test_write_init_array_insert() {
933 let mut section = section!("assets/libqscintilla2/libqscintilla2_qt5.so.15.0.0", INIT_TEST.index);
934
935 let result = ArrayMut::try_from(&mut section);
936 assert!(result.is_ok());
937
938 let mut array = result.unwrap();
939
940 assert_eq!(array.len(),INIT_TEST.length);
941 assert_eq!(array.size(),INIT_TEST.size);
942
943 let result = array.insert(3,123.into());
944 assert!(result.is_ok());
945
946 assert_eq!(array.len(),INIT_TEST.length + 1);
947 assert_eq!(array.size(),INIT_TEST.size + INIT_TEST.entsize);
948
949 let result = array.at(3);
950 assert!(result.is_ok());
951
952 let item = result.unwrap();
953 assert_eq!(item.value(),123);
954 }
955
956 #[test]
957 fn test_write_fini_array_insert() {
958 let mut section = section!("assets/libqscintilla2/libqscintilla2_qt5.so.15.0.0", FINI_TEST.index);
959
960 let result = ArrayMut::try_from(&mut section);
961 assert!(result.is_ok());
962
963 let mut array = result.unwrap();
964
965 assert_eq!(array.len(),FINI_TEST.length);
966 assert_eq!(array.size(),FINI_TEST.size);
967
968 let result = array.insert(1,123.into());
969 assert!(result.is_ok());
970
971 assert_eq!(array.len(),FINI_TEST.length + 1);
972 assert_eq!(array.size(),FINI_TEST.size + FINI_TEST.entsize);
973
974 let result = array.at(1);
975 assert!(result.is_ok());
976
977 let item = result.unwrap();
978 assert_eq!(item.value(),123);
979 }
980
981}