summaryrefslogtreecommitdiff
path: root/tvg
diff options
context:
space:
mode:
Diffstat (limited to 'tvg')
-rw-r--r--tvg/src/lib.rs16
-rw-r--r--tvg/src/path.rs54
2 files changed, 49 insertions, 21 deletions
diff --git a/tvg/src/lib.rs b/tvg/src/lib.rs
index 3b585d7..6b07ff0 100644
--- a/tvg/src/lib.rs
+++ b/tvg/src/lib.rs
@@ -77,19 +77,21 @@ impl<C: Color + std::fmt::Debug> TvgFile<C> {
pub enum TvgError {
#[error("Not a valid TVG file. The magic number was invalid.")]
InvalidFile,
- #[error("Expected version 1, but found version {}", .0)]
+ #[error("Expected version 1, but found version {}.", .0)]
UnsupportedVersion(u8),
- #[error("Found a coordinate range with an index of 3, which is invalid")]
+ #[error("Found a coordinate range with an index of 3, which is invalid.")]
InvalidCoordinateRange,
- #[error("Found a Custom color encoding, which is unsupported")]
+ #[error("Found a Custom color encoding, which is unsupported.")]
UnsupportedColorEncoding,
- #[error("Found a command with an index of {}, which is invalid", .0)]
+ #[error("Found a command with an index of {}, which is invalid.", .0)]
InvalidCommand(u8),
- #[error("Found a style kind with an index of 3, which is invalid")]
+ #[error("Found a style kind with an index of 3, which is invalid.")]
InvalidStyleKind,
- #[error("Polygons must have at least 3 points, found {}", .0)]
+ #[error("Polygons must have at least 3 points, found {}.", .0)]
InvalidPolygon(u32),
- #[error("The end of the document must have a `prim_style_kind` value of 0. Found {}", .0)]
+ #[error("All padding bits must be zero. Found {}.", .0)]
+ NonZeroPadding(u8),
+ #[error("The end of the document must have a `prim_style_kind` value of 0. Found {}.", .0)]
InvalidEndOfDocument(u8),
#[error("{}", .0)]
IoError(#[from] io::Error),
diff --git a/tvg/src/path.rs b/tvg/src/path.rs
index d2bf4fb..2bc0448 100644
--- a/tvg/src/path.rs
+++ b/tvg/src/path.rs
@@ -1,9 +1,19 @@
-use std::io::{self, Read};
+use std::io::Read;
use byteorder::ReadBytesExt;
use num_enum::TryFromPrimitive;
+use raise::yeet;
-use crate::{header::TvgHeader, read_unit, read_varuint, Decode, Point};
+use crate::{header::TvgHeader, read_unit, read_varuint, Decode, Point, TvgError};
+
+/// Returns an error if the padding isn't zero
+fn check_padding(padding: u8) -> Result<(), TvgError> {
+ if padding != 0 {
+ yeet!(TvgError::NonZeroPadding(padding))
+ }
+
+ Ok(())
+}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
#[repr(u8)]
@@ -122,7 +132,11 @@ enum InstructionData {
}
impl InstructionData {
- fn read(reader: &mut impl Read, header: &TvgHeader, kind: InstructionKind) -> io::Result<Self> {
+ fn read(
+ reader: &mut impl Read,
+ header: &TvgHeader,
+ kind: InstructionKind,
+ ) -> Result<Self, TvgError> {
match kind {
InstructionKind::Line => Self::read_line(reader, header),
InstructionKind::HorizontalLine => Self::read_horizontal_line(reader, header),
@@ -135,25 +149,25 @@ impl InstructionData {
}
}
- fn read_line(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> {
+ fn read_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> {
Ok(Self::Line {
position: Point::read(reader, header)?,
})
}
- fn read_horizontal_line(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> {
+ fn read_horizontal_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> {
Ok(Self::HorizontalLine {
x: read_unit(reader, header)?,
})
}
- fn read_vertical_line(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> {
+ fn read_vertical_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> {
Ok(Self::VerticalLine {
y: read_unit(reader, header)?,
})
}
- fn read_cubic_bezier(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> {
+ fn read_cubic_bezier(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> {
Ok(Self::CubicBezier {
control_0: Point::read(reader, header)?,
control_1: Point::read(reader, header)?,
@@ -161,7 +175,10 @@ impl InstructionData {
})
}
- fn read_arc_header(reader: &mut impl Read, header: &TvgHeader) -> io::Result<(bool, Sweep)> {
+ fn read_arc_header(
+ reader: &mut impl Read,
+ header: &TvgHeader,
+ ) -> Result<(bool, Sweep), TvgError> {
// large_arc and sweep are stored in the same byte
let byte = reader.read_u8()?;
let large_arc = (byte & 1) != 0;
@@ -170,10 +187,12 @@ impl InstructionData {
_ => Sweep::Right,
};
+ check_padding((byte & 0b1111_1100) >> 2)?;
+
Ok((large_arc, sweep))
}
- fn read_arc_circle(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> {
+ fn read_arc_circle(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> {
let (large_arc, sweep) = Self::read_arc_header(reader, header)?;
let radius = read_unit(reader, header)?;
let target = Point::read(reader, header)?;
@@ -186,7 +205,7 @@ impl InstructionData {
})
}
- fn read_arc_ellipse(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> {
+ fn read_arc_ellipse(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> {
let (large_arc, sweep) = Self::read_arc_header(reader, header)?;
let radius_x = read_unit(reader, header)?;
let radius_y = read_unit(reader, header)?;
@@ -203,7 +222,7 @@ impl InstructionData {
})
}
- fn read_quadratic_bezier(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> {
+ fn read_quadratic_bezier(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> {
Ok(Self::QuadraticBezier {
control: Point::read(reader, header)?,
target: Point::read(reader, header)?,
@@ -220,12 +239,15 @@ struct Instruction {
}
impl Instruction {
- fn read(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> {
+ fn read(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> {
let byte = reader.read_u8()?;
let instruction_kind =
InstructionKind::try_from_primitive(byte & 0b0000_0111).expect("invalid instruction");
let has_line_width = (byte & 0b0001_0000) != 0;
+ check_padding((byte & 0b0000_1000) >> 3)?;
+ check_padding((byte & 0b1110_0000) >> 5)?;
+
let line_width = has_line_width
.then(|| read_unit(reader, header))
.transpose()?;
@@ -244,7 +266,11 @@ struct Segment {
}
impl Segment {
- fn read(reader: &mut impl Read, header: &TvgHeader, segment_length: u32) -> io::Result<Self> {
+ fn read(
+ reader: &mut impl Read,
+ header: &TvgHeader,
+ segment_length: u32,
+ ) -> Result<Self, TvgError> {
let start = Point::read(reader, header)?;
let mut instructions = Vec::with_capacity(segment_length as usize);
@@ -276,7 +302,7 @@ impl Path {
reader: &mut impl Read,
header: &TvgHeader,
segment_count: u32,
- ) -> io::Result<Self> {
+ ) -> Result<Self, TvgError> {
let mut segment_lengths = Vec::with_capacity(segment_count as usize);
for _ in 0..segment_count {
segment_lengths.push(read_varuint(reader)? + 1);