Skip to main content

re_log_encoding/rrd/
errors.rs

1use re_build_info::CrateVersion;
2use re_chunk::ChunkError;
3use re_protos::common::v1alpha1::ext;
4
5pub type CodecResult<T> = Result<T, CodecError>;
6
7/// Possible errors when encoding and decoding RRD data.
8///
9/// Encoding *never* involves any IO: the only way you can get this error is due to invalid data in
10/// the stream.
11//
12// TODO(cmc): maybe we should split this into read and write errors.
13#[derive(Debug, thiserror::Error)]
14pub enum CodecError {
15    #[error("Invalid encoding options: {0}")]
16    InvalidOptions(#[from] OptionsError),
17
18    #[error(
19        "Data from Rerun version {file}, which is incompatible with the local Rerun version {local}"
20    )]
21    IncompatibleRerunVersion {
22        file: Box<CrateVersion<'static>>,
23        local: Box<CrateVersion<'static>>,
24    },
25
26    #[error("{0}")]
27    NotAnRrd(NotAnRrdError),
28
29    #[error("Data was from an old, incompatible Rerun version")]
30    OldRrdVersion,
31
32    /// Something went wrong when attempting to decode any kind of RRD frame.
33    ///
34    /// There are 3 kinds of RRD frames:
35    /// * [`crate::StreamHeader`]
36    /// * [`crate::MessageHeader`]
37    /// * [`crate::StreamFooter`]
38    #[error("Failed to decode frame: {0}")]
39    FrameDecoding(String),
40
41    #[error("CRC check failed: expected {expected:08x} but got {got:08x}")]
42    CrcMismatch { expected: u32, got: u32 },
43
44    #[error("Arrow IPC deserialization error: {0}")]
45    ArrowDeserialization(::arrow::error::ArrowError),
46
47    #[error(transparent)]
48    GetColumn(#[from] re_arrow_util::GetColumnError),
49
50    /// A column was missing, had the wrong datatype, or had unexpected nulls.
51    #[error(transparent)]
52    Quiver(#[from] quiver::Error),
53
54    #[error("Arrow IPC serialization error: {0}")]
55    ArrowSerialization(::arrow::error::ArrowError),
56
57    #[error("Protobuf encoding error: {0}")]
58    ProtobufEncode(#[from] re_protos::external::prost::EncodeError),
59
60    #[error("Protobuf error: {0}")]
61    ProtobufDecode(#[from] re_protos::external::prost::DecodeError),
62
63    #[error("Could not convert type from protobuf: {0}")]
64    TypeConversion(Box<re_protos::TypeConversionError>),
65
66    #[error("Invalid chunk: {0}")]
67    Chunk(Box<ChunkError>),
68
69    /// This is returned when `ArrowMsg` or `BlueprintActivationCommand` are received with a legacy
70    /// store id (missing the application id) before the corresponding `SetStoreInfo` message. In
71    /// that case, the best effort is to recover by dropping such message with a warning.
72    #[error("Message with an unknown application id was received")]
73    StoreIdMissingApplicationId {
74        store_kind: re_log_types::StoreKind,
75        recording_id: re_log_types::RecordingId,
76    },
77
78    #[error("Unsupported encoding, expected Arrow IPC")]
79    UnsupportedEncoding,
80
81    #[error("Missing record batch")]
82    MissingRecordBatch,
83
84    #[error("lz4 error: {0}")]
85    Lz4(#[from] lz4_flex::block::DecompressError),
86
87    #[error("Sorbet error: {0}")]
88    Sorbet(#[from] re_sorbet::SorbetError),
89
90    #[error("Integer overflow: {0}")]
91    Overflow(#[from] std::num::TryFromIntError),
92
93    #[error("I/O error: {0}")]
94    Io(#[from] std::io::Error),
95
96    #[error("Chunk {chunk_id} not found in manifest")]
97    ChunkNotInManifest { chunk_id: re_chunk::ChunkId },
98
99    #[error("Invalid timeline name: {0}")]
100    InvalidTimelineName(#[from] re_log_types::InvalidTimelineNameError),
101}
102
103const _: () = assert!(
104    std::mem::size_of::<CodecError>() <= 64,
105    "Error type is too large. Try to reduce its size by boxing some of its variants.",
106);
107
108impl From<re_protos::TypeConversionError> for CodecError {
109    fn from(value: re_protos::TypeConversionError) -> Self {
110        Self::TypeConversion(Box::new(value))
111    }
112}
113
114impl From<ChunkError> for CodecError {
115    fn from(value: ChunkError) -> Self {
116        Self::Chunk(Box::new(value))
117    }
118}
119
120impl From<ext::StoreIdMissingApplicationIdError> for CodecError {
121    fn from(value: ext::StoreIdMissingApplicationIdError) -> Self {
122        Self::StoreIdMissingApplicationId {
123            store_kind: value.store_kind,
124            recording_id: value.recording_id,
125        }
126    }
127}
128
129impl From<ext::StoreIdFromProtoError> for CodecError {
130    fn from(value: ext::StoreIdFromProtoError) -> Self {
131        match value {
132            ext::StoreIdFromProtoError::MissingApplicationId(err) => err.into(),
133            ext::StoreIdFromProtoError::InvalidApplicationId(err) => {
134                re_protos::TypeConversionError::from(err).into()
135            }
136        }
137    }
138}
139
140/// When the file does not have the expected .rrd [FourCC](https://en.wikipedia.org/wiki/FourCC) header.
141#[derive(Debug)]
142pub struct NotAnRrdError {
143    pub expected_fourcc: [u8; 4],
144    pub actual_fourcc: [u8; 4],
145}
146
147impl std::fmt::Display for NotAnRrdError {
148    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149        fn format_fourcc(fourcc: [u8; 4]) -> String {
150            String::from_utf8(fourcc.to_vec()).unwrap_or_else(|_err| {
151                // Show as hex instead
152                format!(
153                    "0x{:02X}{:02X}{:02X}{:02X}",
154                    fourcc[0], fourcc[1], fourcc[2], fourcc[3]
155                )
156            })
157        }
158
159        write!(
160            f,
161            "Not an RRD file: expected FourCC header {:?}, got {:?}",
162            format_fourcc(self.expected_fourcc),
163            format_fourcc(self.actual_fourcc),
164        )
165    }
166}
167
168/// On failure to decode [`crate::rrd::EncodingOptions`]
169#[derive(thiserror::Error, Debug)]
170pub enum OptionsError {
171    #[error("Reserved bytes not zero")]
172    UnknownReservedBytes,
173
174    #[error("Unknown compression: {0}")]
175    UnknownCompression(u8),
176
177    // TODO(jan): Remove this at some point, realistically 1-2 releases after 0.23
178    #[error(
179        "You are trying to load an old .rrd file that's not supported by this version of Rerun."
180    )]
181    RemovedMsgPackSerializer,
182
183    #[error("Unknown serializer: {0}")]
184    UnknownSerializer(u8),
185}