block.rs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. use crate::constants::*;
  2. use crate::prelude::*;
  3. use core::any::Any;
  4. /// Interface for serializing and deserializing objects to and from bytes.
  5. ///
  6. /// # Unsafe
  7. ///
  8. /// This trait is unsafe because it allows arbitrary memory interpretation.
  9. /// Implementor should guarantee the object is saved in the way defined by
  10. /// functions `from_bytes` and `to_bytes`.
  11. pub unsafe trait AsBytes
  12. where
  13. Self: Sized,
  14. {
  15. /// Default implementation that deserializes the object from a byte array.
  16. fn from_bytes(bytes: &[u8]) -> Self {
  17. unsafe { core::ptr::read(bytes.as_ptr() as *const Self) }
  18. }
  19. /// Default implementation that serializes the object to a byte array.
  20. fn to_bytes(&self) -> &[u8] {
  21. unsafe { core::slice::from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
  22. }
  23. }
  24. /// Common data block descriptor.
  25. #[derive(Debug, Clone)]
  26. pub struct Block {
  27. /// Physical block id
  28. pub id: PBlockId,
  29. /// Raw block data
  30. pub data: Box<[u8; BLOCK_SIZE]>,
  31. }
  32. impl Default for Block {
  33. fn default() -> Self {
  34. Self {
  35. id: 0,
  36. data: Box::new([0; BLOCK_SIZE]),
  37. }
  38. }
  39. }
  40. impl Block {
  41. /// Create new block with given physical block id and data.
  42. pub fn new(block_id: PBlockId, data: Box::<[u8; BLOCK_SIZE]>) -> Self {
  43. Self { id: block_id, data }
  44. }
  45. /// Read `size` bytes from `offset` in block data.
  46. pub fn read_offset(&self, offset: usize, size: usize) -> &[u8] {
  47. &self.data[offset..offset + size]
  48. }
  49. /// Read bytes from `offset` in block data and interpret it as `T`.
  50. pub fn read_offset_as<'a, T>(&self, offset: usize) -> T
  51. where
  52. T: AsBytes,
  53. {
  54. T::from_bytes(&self.data[offset..])
  55. }
  56. /// Write block data to `offset` with `size`.
  57. pub fn write_offset(&mut self, offset: usize, data: &[u8]) {
  58. self.data[offset..offset + data.len()].copy_from_slice(data);
  59. }
  60. /// Transform `T` to bytes and write it to `offset`.
  61. pub fn write_offset_as<T>(&mut self, offset: usize, value: &T)
  62. where
  63. T: AsBytes,
  64. {
  65. self.write_offset(offset, value.to_bytes());
  66. }
  67. }
  68. /// Common interface for block devices.
  69. pub trait BlockDevice: Send + Sync + Any {
  70. /// Read a block from disk.
  71. fn read_block(&self, block_id: PBlockId) -> Block;
  72. /// Write a block to disk.
  73. fn write_block(&self, block: &Block);
  74. }