1use std::{convert::TryFrom, io};
117
118use byteorder::{ReadBytesExt, WriteBytesExt, BE, LE};
119use serde::{de::Error as _, Deserialize, Deserializer};
120use serde_json::Value;
121
122use crate::{ByteOrder, Decoder, Encoder};
123
124const MAX_INTEGER_SIZE: usize = 8;
125const DEFAULT_LENGTH: usize = 4;
126const DEFAULT_SIGNED: bool = true;
127
128#[derive(Debug, thiserror::Error)]
130pub enum ValidationError {
131 #[error("Invalid length requested: Maximum allowed is {max} but {requested} where requested")]
132 MaxLength { max: usize, requested: usize },
133 #[error("A bitfield with offset {offset} and a width of {width} bits does not fit into a {bytes} bytes field")]
134 BitOffset {
135 bytes: usize,
136 offset: usize,
137 width: usize,
138 },
139 #[error("The requested field size of {requested} bits is insufficient. It must be between 1 and {max} bits")]
140 InvalidBitWidth { max: usize, requested: usize },
141 #[error("Invalid integer schema. Not a bitfield: {bf}; nor an integer: {int}")]
142 InvalidIntegerSchema {
143 bf: Box<ValidationError>,
144 int: Box<ValidationError>,
145 },
146 #[error(
147 "Tried to build a bitfield from a description that has neither 'bits' nor 'bitoffset'"
148 )]
149 NotABitfield,
150}
151
152#[derive(Debug, thiserror::Error)]
154pub enum EncodingError {
155 #[error("The value '{value}' can not be encoded with an integer schema")]
156 InvalidValue { value: String },
157 #[error("Writing to buffer failed: {0}")]
158 WriteFail(#[from] io::Error),
159}
160
161#[derive(Debug, thiserror::Error)]
163pub enum DecodingError {
164 #[error("Reading encoded data failed: {0}")]
165 ReadFail(#[from] io::Error),
166}
167
168impl DecodingError {
169 pub fn due_to_eof(&self) -> bool {
170 matches!(self, Self::ReadFail(e) if e.kind() == std::io::ErrorKind::UnexpectedEof)
171 }
172}
173
174#[derive(Debug, Clone, Deserialize)]
175#[serde(rename_all = "lowercase")]
176pub(crate) struct RawIntegerSchema {
177 #[serde(default)]
178 pub(crate) byteorder: ByteOrder,
179 #[serde(default = "IntegerSchema::default_length")]
180 pub(crate) length: usize,
181 #[serde(default = "IntegerSchema::default_signed")]
182 pub(crate) signed: bool,
183 pub(crate) bits: Option<usize>,
184 #[serde(rename = "bitoffset")]
185 pub(crate) bit_offset: Option<usize>,
186}
187
188#[derive(Debug, Clone, Copy)]
190pub struct PlainInteger {
191 byteorder: ByteOrder,
192 length: usize,
193 signed: bool,
194}
195
196#[derive(Debug, Clone, Copy)]
198pub struct Bitfield {
199 pub(crate) bytes: usize,
200 pub(crate) width: usize,
201 pub(crate) offset: usize,
202}
203
204#[derive(Debug, Clone)]
206pub enum IntegerSchema {
207 Integer(PlainInteger),
208 Bitfield(Bitfield),
209}
210
211impl Default for Bitfield {
212 fn default() -> Self {
213 Self {
214 bytes: 1,
215 width: 1,
216 offset: 0,
217 }
218 }
219}
220
221impl Bitfield {
222 pub fn new(bytes: usize, width: usize, offset: usize) -> Result<Self, ValidationError> {
224 let max_bits = bytes * 8;
225 if bytes > MAX_INTEGER_SIZE {
226 Err(ValidationError::MaxLength {
227 max: MAX_INTEGER_SIZE,
228 requested: bytes,
229 })
230 } else if width + offset > max_bits {
231 Err(ValidationError::BitOffset {
232 bytes,
233 width,
234 offset,
235 })
236 } else if width == 0 || width > max_bits {
237 Err(ValidationError::InvalidBitWidth {
238 max: max_bits,
239 requested: width,
240 })
241 } else {
242 Ok(Self {
243 bytes,
244 width,
245 offset,
246 })
247 }
248 }
249 pub fn bits(&self) -> usize {
251 self.width
252 }
253 pub fn bytes(&self) -> usize {
254 self.bytes
255 }
256 pub fn mask(&self) -> u64 {
258 ((1 << self.width) - 1) << self.offset
259 }
260 pub fn read(&self, value: u64) -> u64 {
262 (value & self.mask()) >> self.offset
263 }
264 pub fn write(&self, value: u64, target: &mut u64) {
266 let value = (value << self.offset) & self.mask();
267 *target |= value;
268 }
269 pub(crate) fn integer(&self) -> PlainInteger {
271 PlainInteger::new(ByteOrder::BigEndian, self.bytes, false)
272 .expect("Invariants of bitfield match those of integer")
273 }
274}
275
276impl Default for PlainInteger {
277 fn default() -> Self {
278 PlainInteger {
279 length: IntegerSchema::default_length(),
280 signed: IntegerSchema::default_signed(),
281 byteorder: Default::default(),
282 }
283 }
284}
285
286impl PlainInteger {
287 pub fn new(byteorder: ByteOrder, length: usize, signed: bool) -> Result<Self, ValidationError> {
288 if length > MAX_INTEGER_SIZE {
289 Err(ValidationError::MaxLength {
290 max: MAX_INTEGER_SIZE,
291 requested: length,
292 })
293 } else {
294 Ok(Self {
295 byteorder,
296 length,
297 signed,
298 })
299 }
300 }
301 pub fn default_long() -> Self {
303 Self {
304 length: 8,
305 ..Default::default()
306 }
307 }
308 pub fn signed_byte() -> Self {
310 Self {
311 length: 1,
312 ..Default::default()
313 }
314 }
315 pub fn unsigned_byte() -> Self {
316 Self {
317 length: 1,
318 signed: false,
319 ..Default::default()
320 }
321 }
322}
323
324impl IntegerSchema {
325 pub fn default_length() -> usize {
326 DEFAULT_LENGTH
327 }
328 pub fn default_signed() -> bool {
329 DEFAULT_SIGNED
330 }
331 pub fn long_int() -> Self {
333 PlainInteger::default_long().into()
334 }
335 pub fn signed_byte() -> Self {
337 PlainInteger::signed_byte().into()
338 }
339 pub fn unsigned_byte() -> Self {
341 PlainInteger::unsigned_byte().into()
342 }
343 pub fn length(&self) -> usize {
345 match self {
346 IntegerSchema::Integer(PlainInteger { length, .. }) => *length,
347 IntegerSchema::Bitfield(Bitfield { bytes, .. }) => *bytes,
348 }
349 }
350 pub fn max_value(&self) -> usize {
352 match self {
353 IntegerSchema::Integer(PlainInteger { length, signed, .. }) => {
354 let mut max = (1 << (length * 8)) - 1;
355 if *signed {
356 max >>= 1;
357 }
358 max
359 }
360 IntegerSchema::Bitfield(Bitfield { width: bits, .. }) => (1 << bits) - 1,
361 }
362 }
363}
364
365impl Default for IntegerSchema {
366 fn default() -> Self {
367 PlainInteger::default().into()
368 }
369}
370
371impl From<Bitfield> for IntegerSchema {
372 fn from(bits: Bitfield) -> Self {
373 IntegerSchema::Bitfield(bits)
374 }
375}
376
377impl From<PlainInteger> for IntegerSchema {
378 fn from(integer: PlainInteger) -> Self {
379 IntegerSchema::Integer(integer)
380 }
381}
382
383impl TryFrom<RawIntegerSchema> for Bitfield {
384 type Error = ValidationError;
385
386 fn try_from(raw: RawIntegerSchema) -> Result<Self, Self::Error> {
387 if raw.bits.is_some() || raw.bit_offset.is_some() {
388 let bits = raw.bits.unwrap_or_else(|| raw.length * 8);
389 let offset = raw.bit_offset.unwrap_or_default();
390 Self::new(raw.length, bits, offset)
391 } else {
392 Err(ValidationError::NotABitfield)
393 }
394 }
395}
396
397impl TryFrom<RawIntegerSchema> for PlainInteger {
398 type Error = ValidationError;
399
400 fn try_from(raw: RawIntegerSchema) -> Result<Self, Self::Error> {
401 Self::new(raw.byteorder, raw.length, raw.signed)
402 }
403}
404
405impl TryFrom<RawIntegerSchema> for IntegerSchema {
406 type Error = ValidationError;
407
408 fn try_from(raw: RawIntegerSchema) -> Result<Self, Self::Error> {
409 match Bitfield::try_from(raw.clone()) {
410 Ok(bf) => Ok(bf.into()),
411 Err(ValidationError::NotABitfield) => PlainInteger::try_from(raw).map(Into::into),
412 Err(e) => Err(e),
413 }
414 }
415}
416
417impl<'de> Deserialize<'de> for IntegerSchema {
418 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
419 where
420 D: Deserializer<'de>,
421 {
422 let raw = RawIntegerSchema::deserialize(deserializer)?;
423 IntegerSchema::try_from(raw).map_err(D::Error::custom)
424 }
425}
426
427impl Encoder for Bitfield {
428 type Error = EncodingError;
429
430 fn encode<W>(&self, target: &mut W, value: &Value) -> Result<usize, Self::Error>
431 where
432 W: io::Write + WriteBytesExt,
433 {
434 let value = value.as_u64().ok_or_else(|| EncodingError::InvalidValue {
435 value: value.to_string(),
436 })?;
437 let mut buffer = 0;
438 self.write(value, &mut buffer);
439 let int = self.integer();
440 int.encode(target, &buffer.into())
441 }
442}
443
444impl Encoder for PlainInteger {
445 type Error = EncodingError;
446
447 fn encode<W>(&self, target: &mut W, value: &Value) -> Result<usize, Self::Error>
448 where
449 W: io::Write + WriteBytesExt,
450 {
451 let value = value.as_i64().ok_or_else(|| EncodingError::InvalidValue {
452 value: value.to_string(),
453 })?;
454 match (self.byteorder, self.signed) {
455 (ByteOrder::BigEndian, true) => target.write_int::<BE>(value, self.length)?,
456 (ByteOrder::BigEndian, false) => target.write_uint::<BE>(value as _, self.length)?,
457 (ByteOrder::LittleEndian, true) => target.write_int::<LE>(value, self.length)?,
458 (ByteOrder::LittleEndian, false) => target.write_uint::<LE>(value as _, self.length)?,
459 };
460
461 Ok(self.length)
462 }
463}
464
465impl Encoder for IntegerSchema {
466 type Error = EncodingError;
467
468 fn encode<W>(&self, target: &mut W, value: &Value) -> Result<usize, Self::Error>
469 where
470 W: io::Write + WriteBytesExt,
471 {
472 match self {
473 IntegerSchema::Integer(schema) => schema.encode(target, value),
474 IntegerSchema::Bitfield(schema) => schema.encode(target, value),
475 }
476 }
477}
478
479impl Decoder for Bitfield {
480 type Error = DecodingError;
481
482 fn decode<R>(&self, target: &mut R) -> Result<Value, Self::Error>
483 where
484 R: io::Read + ReadBytesExt,
485 {
486 let int = self.integer();
487 let int = int.decode(target)?.as_u64().expect("Is always u64.");
488 Ok(self.read(int).into())
489 }
490}
491
492impl Decoder for PlainInteger {
493 type Error = DecodingError;
494
495 fn decode<R>(&self, target: &mut R) -> Result<Value, Self::Error>
496 where
497 R: io::Read + ReadBytesExt,
498 {
499 Ok(match (self.byteorder, self.signed) {
500 (ByteOrder::BigEndian, true) => target.read_int::<BE>(self.length)?.into(),
501 (ByteOrder::BigEndian, false) => target.read_uint::<BE>(self.length)?.into(),
502 (ByteOrder::LittleEndian, true) => target.read_int::<LE>(self.length)?.into(),
503 (ByteOrder::LittleEndian, false) => target.read_uint::<LE>(self.length)?.into(),
504 })
505 }
506}
507
508impl Decoder for IntegerSchema {
509 type Error = DecodingError;
510
511 fn decode<R>(&self, target: &mut R) -> Result<Value, Self::Error>
512 where
513 R: io::Read + ReadBytesExt,
514 {
515 match self {
516 IntegerSchema::Integer(dec) => dec.decode(target),
517 IntegerSchema::Bitfield(dec) => dec.decode(target),
518 }
519 }
520}
521
522#[cfg(test)]
523mod test {
524 use super::*;
525 use anyhow::Result;
526 use serde_json::{from_value, json};
527
528 #[test]
529 fn encode_integer_4_signed() -> Result<()> {
530 let schema_msb = json!({});
531 let schema_msb: IntegerSchema = from_value(schema_msb)?;
532 let schema_lsb = json!({"byteorder": "littleendian"});
533 let schema_lsb: IntegerSchema = from_value(schema_lsb)?;
534 let value: i32 = 0x1234_5678;
535 let json: Value = value.into();
536 let mut buffer = [0; 4];
537
538 assert_eq!(4, schema_msb.encode(&mut buffer.as_mut(), &json)?);
539 let buf_value = i32::from_be_bytes(buffer);
540 assert_eq!(value, buf_value);
541
542 assert_eq!(4, schema_lsb.encode(&mut buffer.as_mut(), &json)?);
543 let buf_value = i32::from_le_bytes(buffer);
544 assert_eq!(value, buf_value);
545
546 Ok(())
547 }
548
549 #[test]
550 fn encode_integer_3_unsigned() -> Result<()> {
551 let schema = json!({
552 "length": 3,
553 "signed": false
554 });
555 let schema_msb: IntegerSchema = from_value(schema)?;
556 let schema = json!({
557 "length": 3,
558 "signed": false,
559 "byteorder": "littleendian"
560 });
561 let schema_lsb: IntegerSchema = from_value(schema)?;
562 let value: i64 = 0x123456;
563 let json: Value = value.into();
564 let mut buffer: Vec<u8> = vec![];
565
566 assert_eq!(3, schema_msb.encode(&mut buffer, &json)?);
567 assert!(matches!(buffer.as_slice(), [0x12, 0x34, 0x56, ..]));
568
569 assert_eq!(3, schema_lsb.encode(&mut buffer, &json)?);
570 assert!(matches!(
571 buffer.as_slice(),
572 [0x12, 0x34, 0x56, 0x56, 0x34, 0x12, ..]
573 ));
574
575 Ok(())
576 }
577
578 #[test]
579 fn masks() -> Result<()> {
580 let b1 = Bitfield::new(1, 1, 0)?;
581 let m1 = 1;
582 assert_eq!(b1.mask(), m1);
583 let b2 = Bitfield::new(2, 3, 9)?;
584 let m2 = 0b1110_0000_0000;
585 assert_eq!(b2.mask(), m2);
586 let b3 = Bitfield::new(4, 32, 0)?;
587 let m3 = 0xFFFF_FFFF;
588 assert_eq!(b3.mask(), m3);
589 Ok(())
590 }
591}