alloy_eips/eip4844/
utils.rs1use crate::eip4844::{FIELD_ELEMENT_BYTES_USIZE, USABLE_BITS_PER_FIELD_ELEMENT};
7
8pub const fn fits_in_fe(data: &[u8]) -> bool {
10 const FIELD_ELEMENT_BYTES_USIZE_PLUS_ONE: usize = FIELD_ELEMENT_BYTES_USIZE + 1;
11
12 match data.len() {
13 FIELD_ELEMENT_BYTES_USIZE_PLUS_ONE.. => false,
14 FIELD_ELEMENT_BYTES_USIZE => data[0] & 0b1100_0000 == 0, _ => true,
16 }
17}
18
19pub const fn minimum_fe_for_bytes(bytes: usize) -> usize {
22 (bytes * 8).div_ceil(USABLE_BITS_PER_FIELD_ELEMENT)
23}
24
25pub const fn minimum_fe(data: &[u8]) -> usize {
27 minimum_fe_for_bytes(data.len())
28}
29
30#[derive(Clone, Copy, Debug)]
32pub struct WholeFe<'a>(&'a [u8]);
33
34impl<'a> WholeFe<'a> {
35 pub(crate) const fn new_unchecked(data: &'a [u8]) -> Self {
36 Self(data)
37 }
38
39 pub const fn new(data: &'a [u8]) -> Option<Self> {
42 if data.len() == FIELD_ELEMENT_BYTES_USIZE && fits_in_fe(data) {
43 Some(Self::new_unchecked(data))
44 } else {
45 None
46 }
47 }
48}
49
50impl AsRef<[u8]> for WholeFe<'_> {
51 fn as_ref(&self) -> &[u8] {
52 self.0
53 }
54}
55
56#[cfg(test)]
57mod test {
58 use crate::eip4844::{FIELD_ELEMENTS_PER_BLOB, USABLE_BYTES_PER_BLOB};
59
60 use super::*;
61 #[test]
62 fn calc_required_fe() {
63 assert_eq!(minimum_fe(&[0u8; 32]), 2);
64 assert_eq!(minimum_fe(&[0u8; 31]), 1);
65 assert_eq!(minimum_fe(&[0u8; 33]), 2);
66 assert_eq!(minimum_fe(&[0u8; 64]), 3);
67 assert_eq!(minimum_fe(&[0u8; 65]), 3);
68 assert_eq!(minimum_fe_for_bytes(USABLE_BYTES_PER_BLOB), FIELD_ELEMENTS_PER_BLOB as usize);
69 }
70
71 #[test]
72 fn calc_is_valid_field_element() {
73 assert!(fits_in_fe(&[0u8; 32]));
74 assert!(!fits_in_fe(&[0u8; 33]));
75
76 assert!(WholeFe::new(&[0u8; 32]).is_some());
77 assert!(WholeFe::new(&[0u8; 33]).is_none());
78 assert!(WholeFe::new(&[0u8; 31]).is_none());
79 }
80}