1#[cfg(not(feature = "std"))]
7extern crate alloc;
8#[cfg(not(feature = "std"))]
9use alloc::{format, vec::Vec};
10
11use super::Span;
12#[cfg(debug_assertions)]
13use core::ops::Range;
14
15#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct Style<'a> {
38 pub name: &'a str,
40
41 pub parent: Option<&'a str>,
43
44 pub fontname: &'a str,
46
47 pub fontsize: &'a str,
49
50 pub primary_colour: &'a str,
52
53 pub secondary_colour: &'a str,
55
56 pub outline_colour: &'a str,
58
59 pub back_colour: &'a str,
61
62 pub bold: &'a str,
64
65 pub italic: &'a str,
67
68 pub underline: &'a str,
70
71 pub strikeout: &'a str,
73
74 pub scale_x: &'a str,
76
77 pub scale_y: &'a str,
79
80 pub spacing: &'a str,
82
83 pub angle: &'a str,
85
86 pub border_style: &'a str,
88
89 pub outline: &'a str,
91
92 pub shadow: &'a str,
94
95 pub alignment: &'a str,
97
98 pub margin_l: &'a str,
100
101 pub margin_r: &'a str,
103
104 pub margin_v: &'a str,
106
107 pub margin_t: Option<&'a str>,
109
110 pub margin_b: Option<&'a str>,
112
113 pub encoding: &'a str,
115
116 pub relative_to: Option<&'a str>,
118
119 pub span: Span,
121}
122
123impl Style<'_> {
124 #[must_use]
143 pub fn to_ass_string(&self) -> alloc::string::String {
144 format!(
147 "Style: {},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}",
148 self.name,
149 self.fontname,
150 self.fontsize,
151 self.primary_colour,
152 self.secondary_colour,
153 self.outline_colour,
154 self.back_colour,
155 self.bold,
156 self.italic,
157 self.underline,
158 self.strikeout,
159 self.scale_x,
160 self.scale_y,
161 self.spacing,
162 self.angle,
163 self.border_style,
164 self.outline,
165 self.shadow,
166 self.alignment,
167 self.margin_l,
168 self.margin_r,
169 self.margin_v,
170 self.encoding
171 )
172 }
173
174 #[must_use]
200 pub fn to_ass_string_with_format(&self, format: &[&str]) -> alloc::string::String {
201 let mut field_values = Vec::with_capacity(format.len());
202
203 for field in format {
204 let value = match *field {
205 "Name" => self.name,
206 "Fontname" => self.fontname,
207 "Fontsize" => self.fontsize,
208 "PrimaryColour" => self.primary_colour,
209 "SecondaryColour" => self.secondary_colour,
210 "OutlineColour" | "TertiaryColour" => self.outline_colour,
211 "BackColour" => self.back_colour,
212 "Bold" => self.bold,
213 "Italic" => self.italic,
214 "Underline" => self.underline,
215 "Strikeout" | "StrikeOut" => self.strikeout,
216 "ScaleX" => self.scale_x,
217 "ScaleY" => self.scale_y,
218 "Spacing" => self.spacing,
219 "Angle" => self.angle,
220 "BorderStyle" => self.border_style,
221 "Outline" => self.outline,
222 "Shadow" => self.shadow,
223 "Alignment" => self.alignment,
224 "MarginL" => self.margin_l,
225 "MarginR" => self.margin_r,
226 "MarginV" => self.margin_v,
227 "MarginT" => self.margin_t.unwrap_or("0"),
228 "MarginB" => self.margin_b.unwrap_or("0"),
229 "Encoding" => self.encoding,
230 "RelativeTo" => self.relative_to.unwrap_or("0"),
231 _ => "", };
233 field_values.push(value);
234 }
235
236 let joined = field_values.join(",");
237 format!("Style: {joined}")
238 }
239
240 #[cfg(debug_assertions)]
248 #[must_use]
249 pub fn validate_spans(&self, source_range: &Range<usize>) -> bool {
250 let spans = [
251 self.name,
252 self.fontname,
253 self.fontsize,
254 self.primary_colour,
255 self.secondary_colour,
256 self.outline_colour,
257 self.back_colour,
258 self.bold,
259 self.italic,
260 self.underline,
261 self.strikeout,
262 self.scale_x,
263 self.scale_y,
264 self.spacing,
265 self.angle,
266 self.border_style,
267 self.outline,
268 self.shadow,
269 self.alignment,
270 self.margin_l,
271 self.margin_r,
272 self.margin_v,
273 self.encoding,
274 ];
275
276 spans.iter().all(|span| {
277 let ptr = span.as_ptr() as usize;
278 source_range.contains(&ptr)
279 })
280 }
281}
282
283impl Default for Style<'_> {
284 fn default() -> Self {
289 Self {
290 name: "Default",
291 parent: None,
292 fontname: "Arial",
293 fontsize: "20",
294 primary_colour: "&Hffffff",
295 secondary_colour: "&H0000ff",
296 outline_colour: "&H000000",
297 back_colour: "&H000000",
298 bold: "0",
299 italic: "0",
300 underline: "0",
301 strikeout: "0",
302 scale_x: "100",
303 scale_y: "100",
304 spacing: "0",
305 angle: "0",
306 border_style: "1",
307 outline: "0",
308 shadow: "0",
309 alignment: "2",
310 margin_l: "10",
311 margin_r: "10",
312 margin_v: "10",
313 margin_t: None,
314 margin_b: None,
315 encoding: "1",
316 relative_to: None,
317 span: Span::new(0, 0, 0, 0),
318 }
319 }
320}
321
322#[cfg(test)]
323mod tests {
324 use super::*;
325 #[cfg(not(feature = "std"))]
326 use alloc::string::String;
327 #[cfg(not(feature = "std"))]
328 use alloc::vec;
329
330 #[test]
331 fn style_default_values() {
332 let style = Style::default();
333 assert_eq!(style.name, "Default");
334 assert_eq!(style.fontname, "Arial");
335 assert_eq!(style.fontsize, "20");
336 assert_eq!(style.primary_colour, "&Hffffff");
337 assert_eq!(style.alignment, "2");
338 }
339
340 #[test]
341 fn style_default_all_fields() {
342 let style = Style::default();
343
344 assert_eq!(style.name, "Default");
346 assert_eq!(style.fontname, "Arial");
347 assert_eq!(style.fontsize, "20");
348 assert_eq!(style.primary_colour, "&Hffffff");
349 assert_eq!(style.secondary_colour, "&H0000ff");
350 assert_eq!(style.outline_colour, "&H000000");
351 assert_eq!(style.back_colour, "&H000000");
352 assert_eq!(style.bold, "0");
353 assert_eq!(style.italic, "0");
354 assert_eq!(style.underline, "0");
355 assert_eq!(style.strikeout, "0");
356 assert_eq!(style.scale_x, "100");
357 assert_eq!(style.scale_y, "100");
358 assert_eq!(style.spacing, "0");
359 assert_eq!(style.angle, "0");
360 assert_eq!(style.border_style, "1");
361 assert_eq!(style.outline, "0");
362 assert_eq!(style.shadow, "0");
363 assert_eq!(style.alignment, "2");
364 assert_eq!(style.margin_l, "10");
365 assert_eq!(style.margin_r, "10");
366 assert_eq!(style.margin_v, "10");
367 assert_eq!(style.encoding, "1");
368 }
369
370 #[test]
371 fn style_clone() {
372 let style = Style::default();
373 let cloned = style.clone();
374 assert_eq!(style, cloned);
375 }
376
377 #[test]
378 fn style_clone_custom() {
379 let style = Style {
380 name: "CustomStyle",
381 parent: None,
382 fontname: "Times New Roman",
383 fontsize: "18",
384 primary_colour: "&H00ff00",
385 secondary_colour: "&Hff0000",
386 outline_colour: "&H0000ff",
387 back_colour: "&H808080",
388 bold: "1",
389 italic: "1",
390 underline: "0",
391 strikeout: "1",
392 scale_x: "110",
393 scale_y: "90",
394 spacing: "2",
395 angle: "15",
396 border_style: "3",
397 outline: "2",
398 shadow: "1",
399 alignment: "5",
400 margin_l: "15",
401 margin_r: "25",
402 margin_v: "20",
403 margin_t: None,
404 margin_b: None,
405 encoding: "0",
406 relative_to: None,
407 span: Span::new(0, 0, 0, 0),
408 };
409
410 let cloned = style.clone();
411 assert_eq!(style, cloned);
412 assert_eq!(cloned.name, "CustomStyle");
413 assert_eq!(cloned.fontname, "Times New Roman");
414 assert_eq!(cloned.bold, "1");
415 }
416
417 #[test]
418 fn style_debug() {
419 let style = Style::default();
420 let debug_str = format!("{style:?}");
421 assert!(debug_str.contains("Style"));
422 assert!(debug_str.contains("Default"));
423 }
424
425 #[test]
426 fn style_debug_custom() {
427 let style = Style {
428 name: "DebugTest",
429 parent: None,
430 fontname: "Helvetica",
431 fontsize: "18",
432 ..Style::default()
433 };
434
435 let debug_str = format!("{style:?}");
436 assert!(debug_str.contains("Style"));
437 assert!(debug_str.contains("DebugTest"));
438 assert!(debug_str.contains("Helvetica"));
439 assert!(debug_str.contains("18"));
440 }
441
442 #[test]
443 fn style_partial_eq() {
444 let style1 = Style::default();
445 let style2 = Style::default();
446 assert_eq!(style1, style2);
447
448 let style3 = Style {
449 name: "Custom",
450 parent: None,
451 ..Style::default()
452 };
453 assert_ne!(style1, style3);
454 }
455
456 #[test]
457 fn style_partial_eq_different_fields() {
458 let base = Style::default();
459
460 let name_diff = Style {
462 name: "Different",
463 parent: None,
464 ..Style::default()
465 };
466 assert_ne!(base, name_diff);
467
468 let font_diff = Style {
469 fontname: "Comic Sans",
470 parent: None,
471 ..Style::default()
472 };
473 assert_ne!(base, font_diff);
474
475 let size_diff = Style {
476 fontsize: "24",
477 parent: None,
478 ..Style::default()
479 };
480 assert_ne!(base, size_diff);
481
482 let color_diff = Style {
483 primary_colour: "&H00ff00",
484 parent: None,
485 ..Style::default()
486 };
487 assert_ne!(base, color_diff);
488 }
489
490 #[test]
491 fn style_field_access() {
492 let style = Style {
493 name: "TestStyle",
494 parent: None,
495 fontname: "Comic Sans",
496 fontsize: "24",
497 bold: "1",
498 italic: "1",
499 ..Style::default()
500 };
501
502 assert_eq!(style.name, "TestStyle");
503 assert_eq!(style.fontname, "Comic Sans");
504 assert_eq!(style.fontsize, "24");
505 assert_eq!(style.bold, "1");
506 assert_eq!(style.italic, "1");
507 }
508
509 #[test]
510 fn style_field_access_comprehensive() {
511 let style = Style {
512 name: "ComprehensiveTest",
513 parent: None,
514 fontname: "Verdana",
515 fontsize: "14",
516 primary_colour: "&Hff0000",
517 secondary_colour: "&H00ff00",
518 outline_colour: "&H0000ff",
519 back_colour: "&Hffffff",
520 bold: "-1",
521 italic: "1",
522 underline: "1",
523 strikeout: "0",
524 scale_x: "125",
525 scale_y: "75",
526 spacing: "3",
527 angle: "45",
528 border_style: "3",
529 outline: "3",
530 shadow: "2",
531 alignment: "9",
532 margin_l: "20",
533 margin_r: "30",
534 margin_v: "15",
535 margin_t: None,
536 margin_b: None,
537 encoding: "2",
538 relative_to: None,
539 span: Span::new(0, 0, 0, 0),
540 };
541
542 assert_eq!(style.name, "ComprehensiveTest");
544 assert_eq!(style.fontname, "Verdana");
545 assert_eq!(style.fontsize, "14");
546 assert_eq!(style.primary_colour, "&Hff0000");
547 assert_eq!(style.secondary_colour, "&H00ff00");
548 assert_eq!(style.outline_colour, "&H0000ff");
549 assert_eq!(style.back_colour, "&Hffffff");
550 assert_eq!(style.bold, "-1");
551 assert_eq!(style.italic, "1");
552 assert_eq!(style.underline, "1");
553 assert_eq!(style.strikeout, "0");
554 assert_eq!(style.scale_x, "125");
555 assert_eq!(style.scale_y, "75");
556 assert_eq!(style.spacing, "3");
557 assert_eq!(style.angle, "45");
558 assert_eq!(style.border_style, "3");
559 assert_eq!(style.outline, "3");
560 assert_eq!(style.shadow, "2");
561 assert_eq!(style.alignment, "9");
562 assert_eq!(style.margin_l, "20");
563 assert_eq!(style.margin_r, "30");
564 assert_eq!(style.margin_v, "15");
565 assert_eq!(style.encoding, "2");
566 }
567
568 #[test]
569 fn style_empty_strings() {
570 let style = Style {
571 name: "",
572 parent: None,
573 fontname: "",
574 fontsize: "",
575 primary_colour: "",
576 secondary_colour: "",
577 outline_colour: "",
578 back_colour: "",
579 bold: "",
580 italic: "",
581 underline: "",
582 strikeout: "",
583 scale_x: "",
584 scale_y: "",
585 spacing: "",
586 angle: "",
587 border_style: "",
588 outline: "",
589 shadow: "",
590 alignment: "",
591 margin_l: "",
592 margin_r: "",
593 margin_v: "",
594 margin_t: None,
595 margin_b: None,
596 encoding: "",
597 relative_to: None,
598 span: Span::new(0, 0, 0, 0),
599 };
600
601 assert_eq!(style.name, "");
603 assert_eq!(style.fontname, "");
604 assert_eq!(style.fontsize, "");
605 assert_eq!(style.primary_colour, "");
606 assert_eq!(style.alignment, "");
607 assert_eq!(style.encoding, "");
608 }
609
610 #[cfg(debug_assertions)]
611 #[test]
612 fn style_validate_spans() {
613 let source = "Default,Arial,20,&Hffffff,&H0000ff,&H000000,&H000000,0,0,0,0,100,100,0,0,1,0,0,2,10,10,10,1";
614 let source_start = source.as_ptr() as usize;
615 let source_end = source_start + source.len();
616 let source_range = source_start..source_end;
617
618 let fields: Vec<&str> = source.split(',').collect();
620 assert_eq!(fields.len(), 23); let style = Style {
624 name: fields[0],
625 parent: None,
626 fontname: fields[1],
627 fontsize: fields[2],
628 primary_colour: fields[3],
629 secondary_colour: fields[4],
630 outline_colour: fields[5],
631 back_colour: fields[6],
632 bold: fields[7],
633 italic: fields[8],
634 underline: fields[9],
635 strikeout: fields[10],
636 scale_x: fields[11],
637 scale_y: fields[12],
638 spacing: fields[13],
639 angle: fields[14],
640 border_style: fields[15],
641 outline: fields[16],
642 shadow: fields[17],
643 alignment: fields[18],
644 margin_l: fields[19],
645 margin_r: fields[20],
646 margin_v: fields[21],
647 margin_t: None,
648 margin_b: None,
649 encoding: fields[22],
650 relative_to: None,
651 span: Span::new(0, 0, 0, 0),
652 };
653
654 assert!(style.validate_spans(&source_range));
656
657 assert_eq!(style.name, "Default");
659 assert_eq!(style.fontname, "Arial");
660 assert_eq!(style.fontsize, "20");
661 }
662
663 #[cfg(debug_assertions)]
664 #[test]
665 fn style_validate_spans_invalid() {
666 let source1 = "Default,Arial,20";
667 let source2 = "Other,Times,16";
668 let source1_start = source1.as_ptr() as usize;
669 let source1_end = source1_start + source1.len();
670 let source1_range = source1_start..source1_end;
671
672 let style = Style {
674 name: &source2[0..5], parent: None,
676 fontname: &source1[8..13], fontsize: &source1[14..16], ..Style::default()
679 };
680
681 assert!(!style.validate_spans(&source1_range));
683 }
684
685 #[test]
686 fn style_lifetimes() {
687 let source = String::from("TestStyle,Times,16");
688 let style = {
689 let parts: Vec<&str> = source.split(',').collect();
690 Style {
691 name: parts[0],
692 parent: None,
693 fontname: parts[1],
694 fontsize: parts[2],
695 ..Style::default()
696 }
697 };
698
699 assert_eq!(style.name, "TestStyle");
700 assert_eq!(style.fontname, "Times");
701 assert_eq!(style.fontsize, "16");
702 }
703
704 #[test]
705 fn style_equality_all_combinations() {
706 let style1 = Style::default();
707 let mut style2 = Style::default();
708
709 assert_eq!(style1, style2);
711
712 style2.name = "Different";
714 assert_ne!(style1, style2);
715 style2 = Style::default();
716
717 style2.fontname = "Different";
718 assert_ne!(style1, style2);
719 style2 = Style::default();
720
721 style2.fontsize = "Different";
722 assert_ne!(style1, style2);
723 style2 = Style::default();
724
725 style2.primary_colour = "Different";
726 assert_ne!(style1, style2);
727 style2 = Style::default();
728
729 style2.secondary_colour = "Different";
730 assert_ne!(style1, style2);
731 style2 = Style::default();
732
733 style2.outline_colour = "Different";
734 assert_ne!(style1, style2);
735 style2 = Style::default();
736
737 style2.back_colour = "Different";
738 assert_ne!(style1, style2);
739 style2 = Style::default();
740
741 style2.bold = "Different";
742 assert_ne!(style1, style2);
743 style2 = Style::default();
744
745 style2.italic = "Different";
746 assert_ne!(style1, style2);
747 style2 = Style::default();
748
749 style2.underline = "Different";
750 assert_ne!(style1, style2);
751 style2 = Style::default();
752
753 style2.strikeout = "Different";
754 assert_ne!(style1, style2);
755 style2 = Style::default();
756
757 style2.scale_x = "Different";
758 assert_ne!(style1, style2);
759 style2 = Style::default();
760
761 style2.scale_y = "Different";
762 assert_ne!(style1, style2);
763 style2 = Style::default();
764
765 style2.spacing = "Different";
766 assert_ne!(style1, style2);
767 style2 = Style::default();
768
769 style2.angle = "Different";
770 assert_ne!(style1, style2);
771 style2 = Style::default();
772
773 style2.border_style = "Different";
774 assert_ne!(style1, style2);
775 style2 = Style::default();
776
777 style2.outline = "Different";
778 assert_ne!(style1, style2);
779 style2 = Style::default();
780
781 style2.shadow = "Different";
782 assert_ne!(style1, style2);
783 style2 = Style::default();
784
785 style2.alignment = "Different";
786 assert_ne!(style1, style2);
787 style2 = Style::default();
788
789 style2.margin_l = "Different";
790 assert_ne!(style1, style2);
791 style2 = Style::default();
792
793 style2.margin_r = "Different";
794 assert_ne!(style1, style2);
795 style2 = Style::default();
796
797 style2.margin_v = "Different";
798 assert_ne!(style1, style2);
799 style2 = Style::default();
800
801 style2.encoding = "Different";
802 assert_ne!(style1, style2);
803 }
804
805 #[test]
806 fn style_default_construction() {
807 let style: Style = Style::default();
809 assert_eq!(style.name, "Default");
810 assert_eq!(style.fontname, "Arial");
811 assert_eq!(style.fontsize, "20");
812 assert_eq!(style.primary_colour, "&Hffffff");
813 assert_eq!(style.secondary_colour, "&H0000ff");
814 assert_eq!(style.outline_colour, "&H000000");
815 assert_eq!(style.back_colour, "&H000000");
816 assert_eq!(style.bold, "0");
817 assert_eq!(style.italic, "0");
818 assert_eq!(style.underline, "0");
819 assert_eq!(style.strikeout, "0");
820 assert_eq!(style.scale_x, "100");
821 assert_eq!(style.scale_y, "100");
822 assert_eq!(style.spacing, "0");
823 assert_eq!(style.angle, "0");
824 assert_eq!(style.border_style, "1");
825 assert_eq!(style.outline, "0");
826 assert_eq!(style.shadow, "0");
827 assert_eq!(style.alignment, "2");
828 assert_eq!(style.margin_l, "10");
829 assert_eq!(style.margin_r, "10");
830 assert_eq!(style.margin_v, "10");
831 assert_eq!(style.encoding, "1");
832 }
833
834 #[test]
835 fn style_struct_creation() {
836 let style = Style {
838 name: "TestName",
839 parent: None,
840 fontname: "TestFont",
841 fontsize: "12",
842 primary_colour: "&H123456",
843 secondary_colour: "&H654321",
844 outline_colour: "&Habcdef",
845 back_colour: "&Hfedcba",
846 bold: "1",
847 italic: "1",
848 underline: "1",
849 strikeout: "1",
850 scale_x: "150",
851 scale_y: "75",
852 spacing: "5",
853 angle: "90",
854 border_style: "2",
855 outline: "1",
856 shadow: "3",
857 alignment: "5",
858 margin_l: "25",
859 margin_r: "35",
860 margin_v: "20",
861 margin_t: None,
862 margin_b: None,
863 encoding: "3",
864 relative_to: None,
865 span: Span::new(0, 0, 0, 0),
866 };
867
868 assert_eq!(style.name, "TestName");
870 assert_eq!(style.fontname, "TestFont");
871 assert_eq!(style.fontsize, "12");
872 assert_eq!(style.primary_colour, "&H123456");
873 assert_eq!(style.secondary_colour, "&H654321");
874 assert_eq!(style.outline_colour, "&Habcdef");
875 assert_eq!(style.back_colour, "&Hfedcba");
876 assert_eq!(style.bold, "1");
877 assert_eq!(style.italic, "1");
878 assert_eq!(style.underline, "1");
879 assert_eq!(style.strikeout, "1");
880 assert_eq!(style.scale_x, "150");
881 assert_eq!(style.scale_y, "75");
882 assert_eq!(style.spacing, "5");
883 assert_eq!(style.angle, "90");
884 assert_eq!(style.border_style, "2");
885 assert_eq!(style.outline, "1");
886 assert_eq!(style.shadow, "3");
887 assert_eq!(style.alignment, "5");
888 assert_eq!(style.margin_l, "25");
889 assert_eq!(style.margin_r, "35");
890 assert_eq!(style.margin_v, "20");
891 assert_eq!(style.encoding, "3");
892 }
893
894 #[test]
895 fn style_mix_default_and_custom() {
896 let style = Style {
898 name: "MixedStyle",
899 parent: None,
900 fontsize: "22",
901 bold: "1",
902 italic: "1",
903 primary_colour: "&Hff00ff",
904 alignment: "7",
905 ..Style::default()
906 };
907
908 assert_eq!(style.name, "MixedStyle");
910 assert_eq!(style.fontsize, "22");
911 assert_eq!(style.bold, "1");
912 assert_eq!(style.italic, "1");
913 assert_eq!(style.primary_colour, "&Hff00ff");
914 assert_eq!(style.alignment, "7");
915
916 assert_eq!(style.fontname, "Arial");
918 assert_eq!(style.underline, "0");
919 assert_eq!(style.strikeout, "0");
920 assert_eq!(style.scale_x, "100");
921 assert_eq!(style.encoding, "1");
922 }
923
924 #[test]
925 fn style_to_ass_string() {
926 let style = Style::default();
927 let ass_string = style.to_ass_string();
928
929 assert_eq!(
930 ass_string,
931 "Style: Default,Arial,20,&Hffffff,&H0000ff,&H000000,&H000000,0,0,0,0,100,100,0,0,1,0,0,2,10,10,10,1"
932 );
933 }
934
935 #[test]
936 fn style_to_ass_string_custom() {
937 let style = Style {
938 name: "Custom",
939 fontname: "Times New Roman",
940 fontsize: "24",
941 primary_colour: "&H00ff00",
942 bold: "-1",
943 italic: "1",
944 scale_x: "95",
945 scale_y: "105",
946 alignment: "5",
947 ..Style::default()
948 };
949
950 let ass_string = style.to_ass_string();
951 assert!(ass_string.contains("Custom,Times New Roman,24"));
952 assert!(ass_string.contains("&H00ff00"));
953 assert!(ass_string.contains("-1,1")); assert!(ass_string.contains("95,105")); assert!(ass_string.contains(",5,")); }
957
958 #[test]
959 fn style_to_ass_string_with_format() {
960 let style = Style {
961 name: "TestStyle",
962 fontname: "Arial",
963 fontsize: "20",
964 ..Style::default()
965 };
966
967 let v4_format = vec![
969 "Name",
970 "Fontname",
971 "Fontsize",
972 "PrimaryColour",
973 "SecondaryColour",
974 "OutlineColour",
975 "BackColour",
976 "Bold",
977 "Italic",
978 "Underline",
979 "StrikeOut",
980 "ScaleX",
981 "ScaleY",
982 "Spacing",
983 "Angle",
984 "BorderStyle",
985 "Outline",
986 "Shadow",
987 "Alignment",
988 "MarginL",
989 "MarginR",
990 "MarginV",
991 "Encoding",
992 ];
993 let v4_string = style.to_ass_string_with_format(&v4_format);
994 assert_eq!(
995 v4_string,
996 "Style: TestStyle,Arial,20,&Hffffff,&H0000ff,&H000000,&H000000,0,0,0,0,100,100,0,0,1,0,0,2,10,10,10,1"
997 );
998
999 let min_format = vec!["Name", "Fontname", "Fontsize"];
1001 let min_string = style.to_ass_string_with_format(&min_format);
1002 assert_eq!(min_string, "Style: TestStyle,Arial,20");
1003
1004 let style_v4pp = Style {
1006 name: "V4++Style",
1007 margin_t: Some("15"),
1008 margin_b: Some("20"),
1009 relative_to: Some("video"),
1010 ..Style::default()
1011 };
1012 let v4pp_format = vec![
1013 "Name",
1014 "Fontname",
1015 "Fontsize",
1016 "PrimaryColour",
1017 "SecondaryColour",
1018 "OutlineColour",
1019 "BackColour",
1020 "Bold",
1021 "Italic",
1022 "Underline",
1023 "StrikeOut",
1024 "ScaleX",
1025 "ScaleY",
1026 "Spacing",
1027 "Angle",
1028 "BorderStyle",
1029 "Outline",
1030 "Shadow",
1031 "Alignment",
1032 "MarginL",
1033 "MarginR",
1034 "MarginT",
1035 "MarginB",
1036 "Encoding",
1037 "RelativeTo",
1038 ];
1039 let v4pp_string = style_v4pp.to_ass_string_with_format(&v4pp_format);
1040 assert!(v4pp_string.contains("V4++Style"));
1041 assert!(v4pp_string.contains(",15,20,")); assert!(v4pp_string.contains(",video")); }
1044
1045 #[cfg(debug_assertions)]
1046 #[test]
1047 fn style_validate_spans_comprehensive() {
1048 let source = "Name,Font,Size,Primary,Secondary,Outline,Back,Bold,Italic,Under,Strike,ScX,ScY,Sp,Ang,Border,Out,Shad,Align,ML,MR,MV,Enc";
1049 let source_start = source.as_ptr() as usize;
1050 let source_end = source_start + source.len();
1051 let source_range = source_start..source_end;
1052
1053 let fields: Vec<&str> = source.split(',').collect();
1054 let style = Style {
1055 name: fields[0],
1056 parent: None,
1057 fontname: fields[1],
1058 fontsize: fields[2],
1059 primary_colour: fields[3],
1060 secondary_colour: fields[4],
1061 outline_colour: fields[5],
1062 back_colour: fields[6],
1063 bold: fields[7],
1064 italic: fields[8],
1065 underline: fields[9],
1066 strikeout: fields[10],
1067 scale_x: fields[11],
1068 scale_y: fields[12],
1069 spacing: fields[13],
1070 angle: fields[14],
1071 border_style: fields[15],
1072 outline: fields[16],
1073 shadow: fields[17],
1074 alignment: fields[18],
1075 margin_l: fields[19],
1076 margin_r: fields[20],
1077 margin_v: fields[21],
1078 margin_t: None,
1079 margin_b: None,
1080 encoding: fields[22],
1081 relative_to: None,
1082 span: Span::new(0, 0, 0, 0),
1083 };
1084
1085 assert!(style.validate_spans(&source_range));
1087 }
1088}