Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate errors #87

Merged
merged 3 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# Releasing

1. Update the version number in [Cargo.toml](./Cargo.toml)
Expand Down
3 changes: 1 addition & 2 deletions examples/count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use las::{Read, Reader};

fn main() {
let path = std::env::args()
.skip(1)
.next()
.nth(1)
.expect("Must provide a path to a las file");
let mut reader = Reader::from_path(path).expect("Unable to open reader");
let npoints = reader
Expand Down
195 changes: 144 additions & 51 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,67 @@
use crate::{header, point, reader, vlr, writer, Transform, Version};
use std::{io, str};
use crate::{point::Format, Transform, Version};
use thiserror::Error;

/// Crate-specific error enum.
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum Error {
/// Feature is not supported by version.
#[error("feature {feature} is not supported by version {version}")]
#[allow(missing_docs)]
Feature {
version: Version,
feature: &'static str,
},
/// The writer is closed.
#[error("the writer is closed")]
ClosedWriter,

/// A wrapper around `las::header::Error`.
#[error(transparent)]
Header(#[from] header::Error),
/// The header size, as computed, is too large.
#[error("the header is too large ({0} bytes) to convert to a raw header")]
HeaderTooLarge(usize),

/// An invalid classification number.
#[error("invalid classification: {0}")]
InvalidClassification(u8),

/// The file signature is not LASF.
#[error("the file signature is not 'LASF': {0:?}")]
InvalidFileSignature([u8; 4]),

/// The value can't have the inverse transform applied.
#[error("the transform {transform} cannot be inversely applied to {n}")]
#[allow(missing_docs)]
InverseTransform { n: f64, transform: Transform },
InvalidInverseTransform {
/// The float.
n: f64,

/// Wrapper around `std::io::Error`.
/// The transform that can't be applied
transform: Transform,
},

/// This is an invalid point format.
///
/// It has a combination of options that can't exist.
#[error("invalid point format: {0}")]
InvalidPointFormat(Format),

/// This is an invalid format number.
#[error("invalid format number: {0}")]
InvalidPointFormatNumber(u8),

/// This is not a valid scanner channel
#[error("invalid scanner channel: {0}")]
InvalidScannerChannel(u8),

/// [std::io::Error]
#[error(transparent)]
Io(#[from] io::Error),
Io(#[from] std::io::Error),

/// The las data is laszip compressed.
#[error(
"the las data is laszip compressed, but laszip compression is not supported by this build"
)]
Laszip,
#[error("the las data is laszip compressed, but the las crate is not built with laz support")]
LaszipNotEnabled,

/// [laz::LasZipError]
#[cfg(feature = "laz")]
#[error(transparent)]
LasZipError(#[from] laz::LasZipError),

/// The laszip vlr was not found, the points cannot be decompressed.
#[cfg(feature = "laz")]
#[error("laszip vlr not found")]
LasZipVlrNotFound,

/// This string is not ASCII.
#[error("this string is not ascii: {0}")]
Expand All @@ -40,45 +71,107 @@ pub enum Error {
#[error("the bytes are not zero-filled: {0:?}")]
NotZeroFilled(Vec<u8>),

/// Wrapper around `las::point::Error`.
#[error(transparent)]
Point(#[from] point::Error),
/// The offset to the start of the evlrs is too small.
#[error("offset to the start of the evlrs is too small: {0}")]
OffsetToEvlrsTooSmall(u64),

/// Wrapper around `las::reader::Error`.
#[error(transparent)]
Reader(#[from] reader::Error),
/// The offset to point data is too large.
#[error("the offset to the point data is too large: {0}")]
OffsetToPointDataTooLarge(usize),

/// The offset to the point data was too small.
#[error("offset to the point data is too small: {0}")]
OffsetToPointDataTooSmall(u32),

/// Overlap points are handled by an attribute on [Point](crate::Point), not by a classification.
#[error("overlap points are handled by the `is_overlap` member of `las::Point`, not by classifications")]
OverlapClassification,

/// The attributes of the point format and point do not match.
#[error("the attributes of the point format ({0}) do not match the point")]
PointAttributesDoNotMatch(Format),

/// The point data record length is too small for the format.
#[error("the point data record length {len} is too small for format {format}")]
PointDataRecordLengthTooLarge {
/// The point format.
format: Format,

/// The length of the point data record.
len: u16,
},

/// Point padding is only allowed when evlrs are present.
#[error("point padding is only allowed when evlrs are present")]
PointPaddingNotAllowed,

/// This is not a valid return number.
#[error("invalid return number {return_number} for version {version:?}")]
ReturnNumber {
/// The return number.
return_number: u8,

/// The version that doesn't support this return number.
version: Option<Version>,
},

/// This string is too long for the target slice.
#[error("string is too long for a slice of length {len}: {string}")]
#[allow(missing_docs)]
StringTooLong { string: String, len: usize },
StringTooLong {
/// The string.
string: String,

/// Wrapper around `std::str::Utf8Error`.
#[error(transparent)]
Utf8(#[from] str::Utf8Error),
/// The target length.
len: usize,
},

/// Wrapper around `las::writer::Error`.
#[error(transparent)]
Writer(#[from] Box<writer::Error>),
/// Too many extended variable length records.
#[error("too many extended variable length records: {0}")]
TooManyEvlrs(usize),

/// Wrapper around `las::vlr::Error`.
#[error(transparent)]
Vlr(#[from] vlr::Error),
/// Too many points for this version.
#[error("too many points for version {version}: {n}")]
TooManyPoints {
/// The number of points.
n: u64,

/// Wrapper around `laz::LasZipError`
#[cfg(feature = "laz")]
#[error("laszip error: {0}")]
LasZipError(laz::LasZipError),
/// The LAS version
version: Version,
},

/// The Laszip vlr was not found, the points cannot be decompressed
#[cfg(feature = "laz")]
#[error("laszip vlr not found")]
LasZipVlrNotFound,
}
/// Too many variable length records.
#[error("too many variable length records: {0}")]
TooManyVlrs(usize),

/// Feature is not supported by version.
#[error("feature {feature} is not supported by version {version}")]
UnsupportedFeature {
/// The LAS version.
version: Version,

/// The feature that is not supported
feature: &'static str,
},

/// The point format is not supported by version.
#[error("version {version} does not support format {format}")]
UnsupportedFormat {
/// The LAS version.
version: Version,

/// The unsupported point format.
format: Format,
},

/// [std::str::Utf8Error]
#[error(transparent)]
Utf8(#[from] std::str::Utf8Error),

/// Wkt is required for this point format.
#[error("wkt is required for this point format: {0}")]
WktRequired(Format),

#[cfg(feature = "laz")]
impl From<laz::LasZipError> for Error {
fn from(error: laz::LasZipError) -> Error {
Error::LasZipError(error)
}
/// The vlr data is too long.
#[error("the vlr is too long: {0}")]
VlrTooLong(usize),
}
12 changes: 5 additions & 7 deletions src/header/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,10 @@ impl Builder {
let n = point_format.len();
match raw_header.point_data_record_length.cmp(&n) {
Ordering::Less => {
return Err(Error::PointDataRecordLength {
return Err(Error::PointDataRecordLengthTooLarge {
format: point_format,
len: raw_header.point_data_record_length,
}
.into())
})
}
Ordering::Equal => {} // pass
Ordering::Greater => point_format.extra_bytes = raw_header.point_data_record_length - n,
Expand Down Expand Up @@ -197,11 +196,10 @@ impl Builder {
}
// TODO check waveforms
if !self.version.supports_point_format(self.point_format) {
return Err(Error::Format {
return Err(Error::UnsupportedFormat {
version: self.version,
format: self.point_format,
}
.into());
});
}
let mut vlrs = Vec::new();
let mut evlrs = Vec::new();
Expand All @@ -222,7 +220,7 @@ impl Builder {
if !evlrs.is_empty() {
self.version.verify_support_for::<Evlrs>()?;
} else if !self.point_padding.is_empty() {
return Err(Error::PointPadding.into());
return Err(Error::PointPaddingNotAllowed);
}
let header = Header {
bounds: self.bounds,
Expand Down
Loading