deaf/tables/
table.rs

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
23/// Shared table interface between Table and TableMut
24pub trait TableView<T>
25where
26    T: TableItem + Default
27{
28    /// Get an immutable reference to the internal section
29    fn section(&self) -> &Section;
30
31    /// Get the name index of the internal section
32    fn name_index(&self) -> usize {
33        self.section().name_index()
34    }
35
36    /// Get an iterator over each item's binary data
37    fn iterator(&self) -> ByteIter {
38        ByteIter::new(
39            self.section().data(),
40            T::delimiter(
41                self.section().entity_size()))
42    }
43
44    /// Get a slice of data that represents an item
45    fn data(&self, index: usize) -> Result<&[u8]> {
46        self.iterator()
47            .nth(index)
48            .ok_or(Error::OutOfBoundsError)
49    }
50
51    /// Get the offset of an item from the index
52    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    /// Get an element from the table
64    fn at(&self, index: usize) -> Result<T> {
65        T::parse(self.data(index)?,self.section())
66    }
67
68    /// Get an element from the table at a byte offset
69    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    /// Get all items from the table
78    fn items(&self) -> Result<Vec<T>> {
79        self.iterator()
80            .map(|b| T::parse(b,self.section()))
81            .collect()
82    }
83
84    /// Get the number of items in the table
85    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    /// Get the number of bytes in the table
94    fn size(&self) -> usize {
95        self.section().body_size()
96    }
97
98    /// Get the layout being used by this table
99    fn layout(&self) -> Layout {
100        self.section().layout()
101    }
102
103    /// Get the width being used by this table
104    fn width(&self) -> Width {
105        self.section().width()
106    }
107
108    /// True if items are all the same size
109    fn has_fixed_size(&self) -> bool {
110        self.section().entity_size() > 0
111    }
112
113    /// True if items can be different sizes
114    fn has_variable_size(&self) -> bool {
115        !self.has_fixed_size()
116    }
117
118}
119
120/// A Section represented as an immutable Table
121pub struct Table<'a,T>
122where
123    T: TableItem + Default
124{
125    item: PhantomData<T>,
126    section: &'a Section
127}
128
129/// A Section represented as a mutable Table
130pub 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    /// Create a new table from the given section
143    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    /// Create a new mutable table for the given section
166    fn new(section: &'a mut Section) -> Self {
167        Self {
168            item: PhantomData {},
169            section: section,
170        }
171    }
172
173    /// Reserve space at an offset in the section
174    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    /// Discard space at an offset in the section
186    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    /// Append an item to the table
198    pub fn append(&mut self, item: T) -> Result<usize> {
199        self.insert(self.len(),item)
200    }
201
202    /// Prepend an item to the table
203    pub fn prepend(&mut self, item: T) -> Result<usize> {
204        self.insert(0,item)
205    }
206
207    /// Insert an item into the table
208    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        // reserve additional space
216        self.reserve(offset,size);
217
218        // get a constrained, mutable slice of bytes
219        let data = self.section.slice_mut(offset,size)?;
220
221        // write the item to the byte slice
222        item.write(data)?;
223
224        Ok(size)
225    }
226
227    /// Remove an item from the table by index
228    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        // remove the data from the buffer
236        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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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}