1#![allow(non_snake_case)]
81
82extern crate byteorder;
83
84#[cfg(doctest)]
85extern crate doc_comment;
86
87#[cfg(doctest)]
88doc_comment::doctest!("../README.md");
89
90use std::borrow::Borrow;
91use std::cell::RefCell;
92use std::fmt;
93use std::io::Cursor;
94use std::io::Seek;
95use std::io::SeekFrom;
96use std::io::Write;
97use std::ops::{Add, Deref, Sub};
98use std::rc::Rc;
99
100use byteorder::{BigEndian, LittleEndian, WriteBytesExt};
101
102#[derive(Clone, Copy, Debug, PartialEq)]
104pub enum Endian {
105 Big,
106 Little,
107}
108
109#[cfg(target_endian = "little")]
111pub const DEFAULT_ENDIAN: Endian = Endian::Little;
112
113#[cfg(target_endian = "big")]
115pub const DEFAULT_ENDIAN: Endian = Endian::Big;
116
117enum BindingValue {
119 Constant(u64),
121 From(Rc<Binding>, i64),
123 Unconstrained,
125}
126
127impl fmt::Debug for BindingValue {
128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 match *self {
130 BindingValue::Constant(v) => write!(f, "Constant({})", v),
131 BindingValue::From(ref b, v) => write!(f, "From({:?}, {})", b, v),
132 BindingValue::Unconstrained => write!(f, "Unconstrained"),
133 }
134 }
135}
136
137struct Binding {
139 value: RefCell<BindingValue>,
140}
141
142impl fmt::Debug for Binding {
143 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144 write!(f, "Binding {{ {:?} }}", self.value.borrow())
145 }
146}
147
148trait BindingOffset {
150 fn get_base_and_offset(&self) -> (Rc<Binding>, i64);
153 fn offset(&self, other: &Rc<Binding>) -> Option<i64>;
155}
156
157impl BindingOffset for Rc<Binding> {
158 fn get_base_and_offset(&self) -> (Rc<Binding>, i64) {
159 match *self.value.borrow().deref() {
160 BindingValue::From(ref b, offset) => {
161 let (base, base_offset) = b.get_base_and_offset();
162 (base, base_offset + offset)
163 }
164 _ => (self.clone(), 0),
166 }
167 }
168
169 fn offset(&self, other: &Rc<Binding>) -> Option<i64> {
170 let (base, offset) = self.get_base_and_offset();
171 let (other_base, other_offset) = other.get_base_and_offset();
172 let base_ptr = base.deref() as *const Binding;
173 let other_base_ptr = other_base.deref() as *const Binding;
174 if base_ptr == other_base_ptr {
175 Some(offset - other_offset)
178 } else {
179 None
181 }
182 }
183}
184
185impl Binding {
186 pub fn unconstrained() -> Binding {
188 Binding {
189 value: RefCell::new(BindingValue::Unconstrained),
190 }
191 }
192 pub fn from(other: Rc<Binding>, offset: i64) -> Binding {
194 Binding {
195 value: RefCell::new(BindingValue::From(other, offset)),
196 }
197 }
198 pub fn constant(val: u64) -> Binding {
200 Binding {
201 value: RefCell::new(BindingValue::Constant(val)),
202 }
203 }
204
205 pub fn set_const(&self, val: u64) {
207 let mut v = self.value.borrow_mut();
208 *v = BindingValue::Constant(val);
209 }
210 pub fn set(&self, other: Rc<Binding>) {
212 let mut v = self.value.borrow_mut();
213 let (base, offset) = other.get_base_and_offset();
214 *v = BindingValue::From(base, offset);
215 }
216 pub fn value(&self) -> Option<u64> {
218 match *self.value.borrow() {
219 BindingValue::Constant(c) => Some(c),
221 BindingValue::From(ref base, addend) => base.value().map(|v| v + addend as u64),
224 _ => None,
226 }
227 }
228}
229
230#[doc(hidden)]
231pub struct RealLabel {
232 binding: Rc<Binding>,
233}
234
235impl fmt::Debug for RealLabel {
236 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
237 write!(f, "{:?}", self.binding)
238 }
239}
240
241pub trait LabelMaker {
243 fn new() -> Self;
245 fn from_const(val: u64) -> Self;
247 fn from_label(other: &Self) -> Self;
249 fn from_label_offset(other: &Self, offset: i64) -> Self;
251}
252
253impl RealLabel {
254 pub fn value(&self) -> Option<u64> {
256 self.binding.value()
257 }
258 pub fn offset(&self, other: &RealLabel) -> Option<i64> {
260 self.binding.offset(&other.binding)
262 }
263 pub fn set_const(&self, val: u64) {
265 self.binding.set_const(val);
266 }
267 pub fn set(&self, other: &RealLabel) {
269 self.binding.set(other.binding.clone())
271 }
272}
273
274impl LabelMaker for RealLabel {
275 fn new() -> RealLabel {
276 RealLabel {
277 binding: Rc::new(Binding::unconstrained()),
278 }
279 }
280 fn from_const(val: u64) -> RealLabel {
281 RealLabel {
282 binding: Rc::new(Binding::constant(val)),
283 }
284 }
285 fn from_label(other: &RealLabel) -> RealLabel {
286 RealLabel {
287 binding: other.binding.clone(),
288 }
289 }
290 fn from_label_offset(other: &RealLabel, offset: i64) -> RealLabel {
291 RealLabel {
292 binding: Rc::new(Binding::from(other.binding.clone(), offset)),
293 }
294 }
295}
296
297#[derive(Clone)]
336pub struct Label(pub Rc<RealLabel>);
337
338impl fmt::Debug for Label {
339 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
340 write!(f, "Label {{ {:?} }}", self.0)
341 }
342}
343
344impl Deref for Label {
345 type Target = RealLabel;
346
347 fn deref(&self) -> &RealLabel {
348 let &Label(ref inner) = self;
349 inner.deref()
350 }
351}
352
353impl LabelMaker for Label {
354 fn new() -> Label {
355 Label(Rc::new(RealLabel::new()))
356 }
357 fn from_const(val: u64) -> Label {
358 Label(Rc::new(RealLabel::from_const(val)))
359 }
360 fn from_label(other: &Label) -> Label {
361 let &Label(ref inner) = other;
362 Label(Rc::new(RealLabel::from_label(inner.borrow())))
363 }
364 fn from_label_offset(other: &Label, offset: i64) -> Label {
365 let &Label(ref inner) = other;
366 Label(Rc::new(RealLabel::from_label_offset(
367 inner.borrow(),
368 offset,
369 )))
370 }
371}
372
373impl<'a> Add<i64> for &'a Label {
377 type Output = Label;
378
379 fn add(self, rhs: i64) -> Label {
380 Label::from_label_offset(self, rhs)
381 }
382}
383
384impl<'a> Sub<i64> for &'a Label {
388 type Output = Label;
389
390 fn sub(self, rhs: i64) -> Label {
391 Label::from_label_offset(self, -rhs)
392 }
393}
394
395impl<'a> Sub<&'a Label> for &'a Label {
399 type Output = i64;
400
401 fn sub(self, rhs: &'a Label) -> i64 {
402 self.offset(rhs).unwrap()
403 }
404}
405
406pub trait Num {}
408
409impl Num for u8 {}
410impl Num for u16 {}
411impl Num for u32 {}
412impl Num for u64 {}
413
414pub enum LabelOrNum<T: Num> {
416 Label(Label),
417 Num(T),
418}
419
420pub trait ToLabelOrNum<'a, T: Num> {
422 fn to_labelornum(self) -> LabelOrNum<T>;
423}
424
425impl<'a, T: Num> ToLabelOrNum<'a, T> for Label {
426 fn to_labelornum(self) -> LabelOrNum<T> {
427 LabelOrNum::Label(self)
428 }
429}
430
431impl<'a, T: Num> ToLabelOrNum<'a, T> for &'a Label {
432 fn to_labelornum(self) -> LabelOrNum<T> {
433 LabelOrNum::Label(self.clone())
434 }
435}
436
437impl<'a, T: Num> ToLabelOrNum<'a, T> for T {
438 fn to_labelornum(self) -> LabelOrNum<T> {
439 LabelOrNum::Num(self)
440 }
441}
442
443#[derive(Clone)]
445struct Reference {
446 label: Label,
448 offset: u64,
450 endian: Endian,
452 size: usize,
454}
455
456pub struct Section {
479 pub endian: Endian,
483 contents: Cursor<Vec<u8>>,
485 references: Vec<Reference>,
487 start: Label,
489 final_size: Label,
491}
492
493impl Section {
494 pub fn new() -> Section {
496 Section::with_endian(DEFAULT_ENDIAN)
497 }
498
499 pub fn with_endian(endian: Endian) -> Section {
501 Section {
502 endian,
503 contents: Cursor::new(vec![]),
504 references: vec![],
505 start: Label::new(),
506 final_size: Label::new(),
507 }
508 }
509
510 pub fn size(&self) -> u64 {
512 self.contents.get_ref().len() as u64
513 }
514
515 pub fn final_size(&self) -> Label {
519 self.final_size.clone()
520 }
521
522 pub fn get_contents(self) -> Option<Vec<u8>> {
527 let mut section = self;
529 section.final_size.set_const(section.size());
530 let references: Vec<Reference> = section.references.to_vec();
531 let mut ok = true;
532 section = references.iter().cloned().fold(section, |s, r| {
533 if let Some(val) = r.label.value() {
534 s.store_label_value(val, r.offset, r.endian, r.size)
535 } else {
536 ok = false;
537 s
538 }
539 });
540 if ok {
541 Some(section.contents.into_inner())
542 } else {
543 None
544 }
545 }
546
547 pub fn start(&self) -> Label {
556 self.start.clone()
557 }
558
559 pub fn here(&self) -> Label {
561 &self.start + self.size() as i64
562 }
563
564 pub fn set_start_const(self, value: u64) -> Section {
566 self.start.set_const(value);
567 self
568 }
569
570 pub fn mark(self, label: &Label) -> Section {
572 label.set(&self.here());
573 self
574 }
575
576 pub fn append_bytes(mut self, data: &[u8]) -> Section {
578 self.contents.write_all(data).unwrap();
579 self
580 }
581
582 pub fn append_section<S: Into<Section>>(mut self, section: S) -> Section {
588 let Section {
589 contents,
590 references,
591 final_size,
592 ..
593 } = section.into();
594 final_size.set_const(contents.get_ref().len() as u64);
595 let current = self.size();
596 self.contents.write_all(&contents.into_inner()).unwrap();
597 self.references.extend(references.into_iter().map(|mut r| {
598 r.offset += current;
599 r
600 }));
601 self
602 }
603
604 pub fn append_repeated(mut self, byte: u8, count: usize) -> Section {
608 for _ in 0..count {
609 self.contents.write_u8(byte).unwrap();
610 }
611 self
612 }
613
614 pub fn align(self, alignment: u64) -> Section {
619 assert!(((alignment - 1) & alignment) == 0);
621 let new_size = (self.size() + alignment - 1) & !(alignment - 1);
622 let add = new_size - self.size();
623 self.append_repeated(0, add as usize)
624 }
625
626 fn store_label_value(mut self, val: u64, offset: u64, endian: Endian, size: usize) -> Section {
627 let current = self.size();
628 if offset != current {
629 self.contents.seek(SeekFrom::Start(offset)).unwrap();
630 }
631 match endian {
632 Endian::Little => match size {
633 1 => self.L8(val as u8),
634 2 => self.L16(val as u16),
635 4 => self.L32(val as u32),
636 8 => self.L64(val),
637 _ => unreachable!("Unhandled label size!"),
638 },
639 Endian::Big => match size {
640 1 => self.B8(val as u8),
641 2 => self.B16(val as u16),
642 4 => self.B32(val as u32),
643 8 => self.B64(val),
644 _ => unreachable!("Unhandled label size!"),
645 },
646 }
647 }
648
649 fn append_label(mut self, label: &Label, endian: Endian, size: usize) -> Section {
653 let current = self.size();
654 if let Some(val) = label.value() {
656 self.store_label_value(val, current, endian, size)
657 } else {
658 self.references.push(Reference {
660 label: label.clone(),
661 offset: current,
662 endian,
663 size,
664 });
665 self.append_repeated(0, size)
667 }
668 }
669
670 pub fn D8<'a, T: ToLabelOrNum<'a, u8>>(mut self, byte: T) -> Section {
675 let endian = self.endian;
676 match byte.to_labelornum() {
677 LabelOrNum::Num(n) => {
678 self.contents.write_u8(n).unwrap();
679 self
680 }
681 LabelOrNum::Label(l) => self.append_label(&l, endian, 1),
682 }
683 }
684 pub fn L8<'a, T: ToLabelOrNum<'a, u8>>(self, byte: T) -> Section {
688 self.D8(byte)
689 }
690 pub fn B8<'a, T: ToLabelOrNum<'a, u8>>(self, byte: T) -> Section {
694 self.D8(byte)
695 }
696
697 pub fn D16<'a, T: ToLabelOrNum<'a, u16>>(self, word: T) -> Section {
702 match self.endian {
703 Endian::Little => self.L16(word),
704 Endian::Big => self.B16(word),
705 }
706 }
707 pub fn L16<'a, T: ToLabelOrNum<'a, u16>>(mut self, word: T) -> Section {
712 match word.to_labelornum() {
713 LabelOrNum::Num(n) => {
714 self.contents.write_u16::<LittleEndian>(n).unwrap();
715 self
716 }
717 LabelOrNum::Label(l) => self.append_label(&l, Endian::Little, 2),
718 }
719 }
720 pub fn B16<'a, T: ToLabelOrNum<'a, u16>>(mut self, word: T) -> Section {
725 match word.to_labelornum() {
726 LabelOrNum::Num(n) => {
727 self.contents.write_u16::<BigEndian>(n).unwrap();
728 self
729 }
730 LabelOrNum::Label(l) => self.append_label(&l, Endian::Big, 2),
731 }
732 }
733
734 pub fn D32<'a, T: ToLabelOrNum<'a, u32>>(self, dword: T) -> Section {
739 match self.endian {
740 Endian::Little => self.L32(dword),
741 Endian::Big => self.B32(dword),
742 }
743 }
744 pub fn L32<'a, T: ToLabelOrNum<'a, u32>>(mut self, dword: T) -> Section {
749 match dword.to_labelornum() {
750 LabelOrNum::Num(n) => {
751 self.contents.write_u32::<LittleEndian>(n).unwrap();
752 self
753 }
754 LabelOrNum::Label(l) => self.append_label(&l, Endian::Little, 4),
755 }
756 }
757 pub fn B32<'a, T: ToLabelOrNum<'a, u32>>(mut self, dword: T) -> Section {
762 match dword.to_labelornum() {
763 LabelOrNum::Num(n) => {
764 self.contents.write_u32::<BigEndian>(n).unwrap();
765 self
766 }
767 LabelOrNum::Label(l) => self.append_label(&l, Endian::Big, 4),
768 }
769 }
770
771 pub fn D64<'a, T: ToLabelOrNum<'a, u64>>(self, qword: T) -> Section {
776 match self.endian {
777 Endian::Little => self.L64(qword),
778 Endian::Big => self.B64(qword),
779 }
780 }
781 pub fn L64<'a, T: ToLabelOrNum<'a, u64>>(mut self, qword: T) -> Section {
786 match qword.to_labelornum() {
787 LabelOrNum::Num(n) => {
788 self.contents.write_u64::<LittleEndian>(n).unwrap();
789 self
790 }
791 LabelOrNum::Label(l) => self.append_label(&l, Endian::Little, 8),
792 }
793 }
794 pub fn B64<'a, T: ToLabelOrNum<'a, u64>>(mut self, qword: T) -> Section {
799 match qword.to_labelornum() {
800 LabelOrNum::Num(n) => {
801 self.contents.write_u64::<BigEndian>(n).unwrap();
802 self
803 }
804 LabelOrNum::Label(l) => self.append_label(&l, Endian::Big, 8),
805 }
806 }
807}
808
809impl Default for Section {
810 fn default() -> Self {
811 Section::new()
812 }
813}
814
815#[test]
816fn binding_offset() {
817 let b_u = Rc::new(Binding::unconstrained());
818 let b_c = Rc::new(Binding::constant(1));
819 let b_f1 = Rc::new(Binding::from(b_u.clone(), 0));
820 assert_eq!(b_f1.offset(&b_u).unwrap(), 0);
822 assert!(b_f1.offset(&b_c).is_none());
824 assert!(b_u.offset(&b_c).is_none());
826 assert!(b_c.offset(&b_u).is_none());
827
828 let b_f2 = Rc::new(Binding::from(b_c.clone(), 10));
829 assert_eq!(b_f2.offset(&b_c).unwrap(), 10);
831 let b_f3 = Rc::new(Binding::from(b_f1.clone(), 10));
833 assert_eq!(b_f3.offset(&b_u).unwrap(), 10);
834 let b_f4 = Rc::new(Binding::from(b_f3.clone(), 10));
835 assert_eq!(b_f4.offset(&b_u).unwrap(), 20);
836 let b_f5 = Rc::new(Binding::from(b_u.clone(), 10));
840 let b_f6 = Rc::new(Binding::from(b_f5.clone(), 10));
841 assert_eq!(b_f6.offset(&b_f5).unwrap(), 10);
842 assert_eq!(b_f6.offset(&b_u).unwrap(), 20);
843 assert_eq!(b_f6.offset(&b_f4).unwrap(), 0);
846 assert_eq!(b_f6.offset(&b_f3).unwrap(), 10);
848 assert_eq!(b_f3.offset(&b_f6).unwrap(), -10);
849}
850
851#[test]
852fn binding_value() {
853 let b_u = Rc::new(Binding::unconstrained());
854 let b_c = Rc::new(Binding::constant(1));
855 let b_f1 = Rc::new(Binding::from(b_u.clone(), 0));
856 assert!(b_u.value().is_none());
857 assert_eq!(b_c.value().unwrap(), 1);
858 assert!(b_f1.value().is_none());
859
860 let b_f2 = Rc::new(Binding::from(b_c.clone(), 10));
861 assert_eq!(b_f2.value().unwrap(), 11);
862 let b_f3 = Rc::new(Binding::from(b_f1.clone(), 10));
864 assert!(b_f3.value().is_none());
865 let b_f4 = Rc::new(Binding::from(b_f3.clone(), 10));
866 assert!(b_f4.value().is_none());
867
868 let b_f5 = Rc::new(Binding::from(b_f2.clone(), 10));
869 assert_eq!(b_f5.value().unwrap(), 21);
870}
871
872#[test]
873fn label_unconstrained() {
874 let l = Label::new();
875 assert!(l.value().is_none());
876}
877
878#[test]
879fn label_const() {
880 let l = Label::from_const(10);
881 assert_eq!(l.value().unwrap(), 10);
882}
883
884#[test]
885fn label_label() {
886 let l1 = Label::new();
887 let l2 = Label::from_label(&l1);
888 assert!(l2.value().is_none());
889 assert_eq!(l2.offset(&l1).unwrap(), 0);
891 assert_eq!(l1.offset(&l2).unwrap(), 0);
892}
893
894#[test]
895fn label_label_offset() {
896 let l1 = Label::new();
897 let l2 = Label::from_label_offset(&l1, 10);
898 assert!(l2.value().is_none());
899 assert_eq!(l2.offset(&l1).unwrap(), 10);
900 assert_eq!(l1.offset(&l2).unwrap(), -10);
901
902 let l3 = Label::from_label_offset(&l2, 10);
903 assert_eq!(l3.offset(&l2).unwrap(), 10);
904 assert_eq!(l2.offset(&l3).unwrap(), -10);
905 assert_eq!(l3.offset(&l1).unwrap(), 20);
906 assert_eq!(l1.offset(&l3).unwrap(), -20);
907
908 let l4 = Label::from_label_offset(&l3, 10);
909 assert_eq!(l4.offset(&l1).unwrap(), 30);
910
911 let l5 = Label::from_label_offset(&l1, 10);
913 assert_eq!(l5.offset(&l2).unwrap(), 0);
915 assert_eq!(l5.offset(&l3).unwrap(), -10);
916 assert_eq!(l3.offset(&l5).unwrap(), 10);
917}
918
919#[test]
920fn label_offset_unrelated() {
921 let l1 = Label::new();
922 let l2 = Label::new();
923 assert!(l2.offset(&l1).is_none());
924 assert!(l1.offset(&l2).is_none());
925}
926
927#[test]
928fn label_add() {
929 let l1 = Label::new();
930 let l2 = &l1 + 10;
931 assert_eq!(l2.offset(&l1).unwrap(), 10);
932}
933
934#[test]
935fn label_sub() {
936 let l1 = Label::new();
937 let l2 = &l1 - 10;
938 assert_eq!(l2.offset(&l1).unwrap(), -10);
939}
940
941#[test]
942fn label_sub_label() {
943 let l1 = Label::new();
944 let l2 = &l1 + 10;
945 assert_eq!(&l2 - &l1, 10);
946}
947
948#[test]
949fn label_set_const() {
950 let l = Label::new();
951 let val = 0x12345678;
952 l.set_const(val);
953 assert_eq!(l.value().unwrap(), val);
954}
955
956#[test]
957fn label_set() {
958 let val = 0x12345678;
959 let l1 = Label::from_const(val);
960 let l2 = Label::new();
961 l2.set(&l1);
962 assert_eq!(l2.value().unwrap(), val);
963 let l3 = Label::new();
965 let l4 = Label::new();
966 l4.set(&l3);
967 l3.set_const(val);
968 assert_eq!(l4.value().unwrap(), val);
969}
970
971#[test]
972fn section_construction() {
973 let s = Section::new();
974 assert_eq!(s.endian, DEFAULT_ENDIAN);
975
976 let s2 = Section::with_endian(Endian::Little);
977 assert_eq!(s2.endian, Endian::Little);
978}
979
980#[test]
981fn section_append_bytes() {
982 let s = Section::new();
983 let b1 = [0, 1, 2, 3, 4];
984 let b2 = [0xf, 0xe, 0xd, 0xc, 0xb];
985 assert_eq!(
986 s.append_bytes(&b1)
987 .append_bytes(&b2)
988 .get_contents()
989 .unwrap(),
990 &[0, 1, 2, 3, 4, 0xf, 0xe, 0xd, 0xc, 0xb]
991 );
992}
993
994#[test]
995fn section_final_size() {
996 let s = Section::new();
997 let size = s.final_size();
998 s.append_repeated(0, 20).get_contents().unwrap();
999 assert_eq!(size.value().unwrap(), 20);
1000}
1001
1002#[test]
1003fn section_append_section_simple() {
1004 assert_eq!(
1005 Section::new()
1006 .D8(0xab)
1007 .append_section(Section::new().D8(0xcd))
1008 .D8(0xef)
1009 .get_contents()
1010 .unwrap(),
1011 &[0xab, 0xcd, 0xef]
1012 );
1013}
1014
1015#[test]
1016fn section_append_section_labels() {
1017 let mut s = Section::new();
1018 let l1 = Label::from_const(0x12);
1019 let l2 = Label::new();
1020 s = s.D8(0xab);
1021 {
1022 s = s.append_section(Section::new().D8(0xcd).D8(&l1).D8(&l2));
1023 }
1024 s = s.D8(0xef);
1025 l2.set_const(0x34);
1026 assert_eq!(s.get_contents().unwrap(), &[0xab, 0xcd, 0x12, 0x34, 0xef]);
1027}
1028
1029#[test]
1030fn section_append_section_final_size() {
1031 let s = Section::new().D8(0xcd);
1032 assert_eq!(
1033 Section::new()
1034 .D8(0xab)
1035 .D8(s.final_size())
1036 .append_section(s)
1037 .D8(0xef)
1038 .get_contents()
1039 .unwrap(),
1040 &[0xab, 1, 0xcd, 0xef]
1041 );
1042}
1043
1044#[test]
1045fn section_append_repeated() {
1046 let s = Section::new();
1047 assert_eq!(
1048 s.append_repeated(0xff, 5).get_contents().unwrap(),
1049 &[0xff, 0xff, 0xff, 0xff, 0xff]
1050 );
1051}
1052
1053#[test]
1054fn section_align() {
1055 let s = Section::new();
1056 assert_eq!(
1057 s.D8(1).align(8).D8(1).get_contents().unwrap(),
1058 &[1, 0, 0, 0, 0, 0, 0, 0, 1]
1059 );
1060}
1061
1062#[test]
1063fn section_test_8() {
1064 let s = Section::new();
1065 assert_eq!(
1066 s.D8(0x12).L8(0x12).B8(0x12).get_contents().unwrap(),
1067 &[0x12, 0x12, 0x12]
1068 );
1069}
1070
1071#[test]
1072fn section_test_16() {
1073 let s = Section::with_endian(Endian::Little);
1074 assert_eq!(
1075 s.D16(0xABCD)
1076 .L16(0xABCD)
1077 .B16(0xABCD)
1078 .get_contents()
1079 .unwrap(),
1080 &[0xCD, 0xAB, 0xCD, 0xAB, 0xAB, 0xCD]
1081 );
1082}
1083
1084#[test]
1085fn section_test_32() {
1086 let s = Section::with_endian(Endian::Little);
1087 assert_eq!(
1088 s.D32(0xABCD1234)
1089 .L32(0xABCD1234)
1090 .B32(0xABCD1234)
1091 .get_contents()
1092 .unwrap(),
1093 &[0x34, 0x12, 0xCD, 0xAB, 0x34, 0x12, 0xCD, 0xAB, 0xAB, 0xCD, 0x12, 0x34]
1094 );
1095}
1096
1097#[test]
1098fn section_test_64() {
1099 let s = Section::with_endian(Endian::Little);
1100 assert_eq!(
1101 s.D64(0x12345678ABCDEFFF)
1102 .L64(0x12345678ABCDEFFF)
1103 .B64(0x12345678ABCDEFFF)
1104 .get_contents()
1105 .unwrap(),
1106 &[
1107 0xFF, 0xEF, 0xCD, 0xAB, 0x78, 0x56, 0x34, 0x12, 0xFF, 0xEF, 0xCD, 0xAB, 0x78, 0x56,
1108 0x34, 0x12, 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF, 0xFF
1109 ]
1110 );
1111}
1112
1113#[test]
1114fn section_d8l_const_label() {
1115 let l = Label::from_const(10);
1116 let s = Section::with_endian(Endian::Little);
1117 assert_eq!(
1118 s.D8(&l).L8(&l).B8(&l).get_contents().unwrap(),
1119 &[10, 10, 10]
1120 );
1121}
1122
1123#[test]
1124fn section_d16l_const_label() {
1125 let l = Label::from_const(0xABCD);
1126 let s = Section::with_endian(Endian::Little);
1127 assert_eq!(
1128 s.D16(&l).L16(&l).B16(&l).get_contents().unwrap(),
1129 &[0xCD, 0xAB, 0xCD, 0xAB, 0xAB, 0xCD]
1130 );
1131}
1132
1133#[test]
1134fn section_d32l_const_label() {
1135 let l = Label::from_const(0xABCD1234);
1136 let s = Section::with_endian(Endian::Little);
1137 assert_eq!(
1138 s.D32(&l).L32(&l).B32(&l).get_contents().unwrap(),
1139 &[0x34, 0x12, 0xCD, 0xAB, 0x34, 0x12, 0xCD, 0xAB, 0xAB, 0xCD, 0x12, 0x34]
1140 );
1141}
1142
1143#[test]
1144fn section_d64l_const_label() {
1145 let l = Label::from_const(0xABCD12345678F00D);
1146 let s = Section::with_endian(Endian::Little);
1147 assert_eq!(
1148 s.D64(&l).L64(&l).B64(&l).get_contents().unwrap(),
1149 &[
1150 0x0D, 0xF0, 0x78, 0x56, 0x34, 0x12, 0xCD, 0xAB, 0x0D, 0xF0, 0x78, 0x56, 0x34, 0x12,
1151 0xCD, 0xAB, 0xAB, 0xCD, 0x12, 0x34, 0x56, 0x78, 0xF0, 0x0D
1152 ]
1153 );
1154}
1155
1156#[test]
1157fn section_get_contents_label_no_value() {
1158 let l = Label::new();
1161 let s = Section::with_endian(Endian::Little);
1162 assert!(s.D8(&l).get_contents().is_none());
1163}
1164
1165#[test]
1166fn section_label_assign_late() {
1167 let l = Label::new();
1168 let mut s = Section::with_endian(Endian::Little);
1169 s = s.D8(&l).L8(&l).B8(&l);
1170 l.set_const(10);
1172 assert_eq!(s.get_contents().unwrap(), &[10, 10, 10]);
1173}
1174
1175#[test]
1176fn section_start_here() {
1177 let mut s = Section::with_endian(Endian::Little);
1178 s = s.append_repeated(0, 10);
1179 let start = s.start();
1180 let mut here = s.here();
1181 assert_eq!(here.offset(&start).unwrap(), 10);
1182 s = s.append_repeated(0, 10);
1183 here = s.here();
1184 assert_eq!(here.offset(&start).unwrap(), 20);
1185}
1186
1187#[test]
1188fn section_start_mark() {
1189 let s = Section::with_endian(Endian::Little);
1190 let start = s.start();
1191 let marked = Label::new();
1192 s.append_repeated(0, 10)
1193 .mark(&marked)
1194 .append_repeated(0, 10);
1195 assert_eq!(marked.offset(&start).unwrap(), 10);
1196}
1197
1198#[test]
1199fn section_additional_methods_trait() {
1200 trait ExtraSection {
1201 fn add_a_thing(self) -> Section;
1202 }
1203
1204 impl ExtraSection for Section {
1205 fn add_a_thing(self) -> Section {
1206 self.B8(0x12).B16(0x3456).B32(0x7890abcd)
1207 }
1208 }
1209
1210 assert_eq!(
1211 Section::new()
1212 .D8(0)
1213 .add_a_thing()
1214 .D8(1)
1215 .get_contents()
1216 .unwrap(),
1217 &[0, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 1]
1218 );
1219}
1220
1221#[test]
1222fn test_simple_labels() {
1223 let start = Label::new();
1224 let end = Label::new();
1225
1226 let _section = Section::new().mark(&start).mark(&end);
1227
1228 assert_eq!(start.offset(&end), Some(0));
1229}
1230
1231#[test]
1232fn test_set_start_const() {
1233 let l = Label::new();
1234 Section::new()
1235 .set_start_const(0)
1236 .append_repeated(0, 10)
1237 .mark(&l)
1238 .get_contents()
1239 .unwrap();
1240 assert_eq!(l.value().unwrap(), 10);
1241}
1242
1243#[test]
1244fn section_bigendian_defaults() {
1245 let s = Section::with_endian(Endian::Big);
1246 assert_eq!(
1247 s.D8(0x12)
1248 .D16(0x1234)
1249 .D32(0x12345678)
1250 .D64(0x12345678ABCDEFFF)
1251 .get_contents()
1252 .unwrap(),
1253 &[
1254 0x12, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF,
1255 0xFF
1256 ]
1257 );
1258}